dexplo / dataframe_image

A python package for embedding pandas DataFrames as images into pdf and markdown documents
https://dexplo.org/dataframe_image
MIT License
282 stars 41 forks source link

AttributeError: 'ColormapRegistry' object has no attribute 'get_cmap' #74

Closed LysSanzMoreta closed 1 year ago

LysSanzMoreta commented 1 year ago

Whops, I cannot use the background_gradient styler while also exporting because I get the following error:

Packages versions:

Python 3.8.13
Dataframe_image 0.1.5
Matplotlib 3.6.0
Pandas: 1.5.2

Code to reproduce error:

import pandas as pd
import dataframe_image as dfi
aa_dict = {"A":{"a1":1,"a2":2},"B":{"a1":3,"a2":4}}
df = pd.DataFrame.from_dict(aa_dict)
df_styled = df.style.background_gradient(axis=None)
dfi.export(df_styled,"df_experiment.png",dpi=600)

Error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/lys/miniconda3/lib/python3.8/site-packages/dataframe_image/_pandas_accessor.py", line 48, in export
    return _export(
  File "/home/lys/miniconda3/lib/python3.8/site-packages/dataframe_image/_pandas_accessor.py", line 113, in _export
    html = styler2html(obj)
  File "/home/lys/miniconda3/lib/python3.8/site-packages/dataframe_image/pd_html.py", line 8, in styler2html
    html = style.to_html()
  File "/home/lys/miniconda3/lib/python3.8/site-packages/pandas/io/formats/style.py", line 1371, in to_html
    html = obj._render_html(
  File "/home/lys/miniconda3/lib/python3.8/site-packages/pandas/io/formats/style_render.py", line 199, in _render_html
    d = self._render(sparse_index, sparse_columns, max_rows, max_cols, "&nbsp;")
  File "/home/lys/miniconda3/lib/python3.8/site-packages/pandas/io/formats/style_render.py", line 163, in _render
    self._compute()
  File "/home/lys/miniconda3/lib/python3.8/site-packages/pandas/io/formats/style_render.py", line 251, in _compute
    r = func(self)(*args, **kwargs)
  File "/home/lys/miniconda3/lib/python3.8/site-packages/pandas/io/formats/style.py", line 1713, in _apply
    result = func(data, **kwargs)
  File "/home/lys/miniconda3/lib/python3.8/site-packages/pandas/io/formats/style.py", line 3936, in _background_gradient
    rgbas = mpl.colormaps.get_cmap(cmap)(norm(gmap))
AttributeError: 'ColormapRegistry' object has no attribute 'get_cmap'

Side note: i can export if I do not use the background_gradient styler

Thanks!!!

PaleNeutron commented 1 year ago

I think it is not a problem related to dfi.

Try replace the last line with:

df_styled.to_html()

And see if the same error occors.

LysSanzMoreta commented 1 year ago

Hi! I think I had already tried something similar and did not work. I gave it a try anyways (if this is what you mean...):

import pandas as pd
import dataframe_image as dfi
aa_dict = {"A":{"a1":1,"a2":2},"B":{"a1":3,"a2":4}}
df = pd.DataFrame.from_dict(aa_dict)
df_styled = df.style.background_gradient(axis=None)
dfi.export(df_styled.to_html(),"df_experiment.png",dpi=600)

And the error is the same

Thanks!

PaleNeutron commented 1 year ago

Hi! I think I had already tried something similar and did not work. I gave it a try anyways (if this is what you mean...):

import pandas as pd
import dataframe_image as dfi
aa_dict = {"A":{"a1":1,"a2":2},"B":{"a1":3,"a2":4}}
df = pd.DataFrame.from_dict(aa_dict)
df_styled = df.style.background_gradient(axis=None)
dfi.export(df_styled.to_html(),"df_experiment.png",dpi=600)

And the error is the same

Thanks!

I mean to html without dfi. I think this error is not related to this module.

import pandas as pd

aa_dict = {"A":{"a1":1,"a2":2},"B":{"a1":3,"a2":4}}
df = pd.DataFrame.from_dict(aa_dict)
df_styled = df.style.background_gradient(axis=None)
df_styled.to_html()
LysSanzMoreta commented 1 year ago

Oh, ok, yes sorry for the confusion. I did it correctly now and get the same error, indeed.

Is it a pandas.style.to_html() issue then? Should I report it to them?

Thanks!

PaleNeutron commented 1 year ago

I never heard a problem about this, maybe you need to confirm your env first.

LysSanzMoreta commented 1 year ago

Ok, just to confirm, do you want to check the "environment" as in all the installed packages? Or else?

On-ryo commented 1 year ago

I have the same problem with this code: Correlation function itself works well

corr = df.corr(method='spearman', min_periods=3, numeric_only = True)
corr.style.background_gradient(cmap='coolwarm')
huo-shan-long commented 1 year ago

Have you solved this problem?

huo-shan-long commented 1 year ago

I have the same problem with this code: Correlation function itself works well

corr = df.corr(method='spearman', min_periods=3, numeric_only = True)
corr.style.background_gradient(cmap='coolwarm')

Have you solved this problem?

LysSanzMoreta commented 1 year ago

@huo-shan-long At that time I simply just solved it by "not using the background_gradient styler". I need this functionality again, so I will see if things have changed.

I have upgraded dataframe_image to 0.1.11with the same issue

Working on a work-around

LysSanzMoreta commented 1 year ago

@huo-shan-long @On-ryo @PaleNeutron Ok. I found a work-around. If you manually modify the function _background_gradient() in this script in the pandas package .../python3.8/site-packages/pandas/io/formats/style.df:

Like this:

        if mpl_ge_3_6_0():
            if cmap is None:
                try:
                    rgbas = mpl.colormaps[mpl.rcParams["image.cmap"]](norm(gmap))
                except:
                    rgbas = plt.cm.get_cmap(cmap)(norm(gmap))
            else:
                try:
                    rgbas = mpl.colormaps.get_cmap(cmap)(norm(gmap))
                except:
                    rgbas = plt.cm.get_cmap(cmap)(norm(gmap)) #this works
        else:
            rgbas = plt.cm.get_cmap(cmap)(norm(gmap))

There seems to be a bug on some matplotlib compatibility. I used the ugly try-except combo because I am not sure if the condition if mpl_ge_3_6_0()is important in another context. Otherwise I would just remove that.

huo-shan-long commented 1 year ago

@huo-shan-long @On-ryo @PaleNeutron Ok. I found a work-around. If you manually modify the function _background_gradient() in this script in the pandas package .../python3.8/site-packages/pandas/io/formats/style.df:

Like this:

        if mpl_ge_3_6_0():
            if cmap is None:
                try:
                    rgbas = mpl.colormaps[mpl.rcParams["image.cmap"]](norm(gmap))
                except:
                    rgbas = plt.cm.get_cmap(cmap)(norm(gmap))
            else:
                try:
                    rgbas = mpl.colormaps.get_cmap(cmap)(norm(gmap))
                except:
                    rgbas = plt.cm.get_cmap(cmap)(norm(gmap)) #this works
        else:
            rgbas = plt.cm.get_cmap(cmap)(norm(gmap))

There seems to be a bug on some matplotlib compatibility. I used the ugly try-except combo because I am not sure if the condition if mpl_ge_3_6_0()is important in another context. Otherwise I would just remove that.

I solved the problem, the pandas version at the beginning was 2.0.2, after I downgraded version it to 1.5.3, it worked.

LysSanzMoreta commented 1 year ago

@huo-shan-long yeah, it is a version problem, but if you do not want to downgrade, the previous works

PaleNeutron commented 1 year ago

@huo-shan-long @On-ryo @PaleNeutron Ok. I found a work-around. If you manually modify the function _background_gradient() in this script in the pandas package .../python3.8/site-packages/pandas/io/formats/style.df:

Like this:

        if mpl_ge_3_6_0():
            if cmap is None:
                try:
                    rgbas = mpl.colormaps[mpl.rcParams["image.cmap"]](norm(gmap))
                except:
                    rgbas = plt.cm.get_cmap(cmap)(norm(gmap))
            else:
                try:
                    rgbas = mpl.colormaps.get_cmap(cmap)(norm(gmap))
                except:
                    rgbas = plt.cm.get_cmap(cmap)(norm(gmap)) #this works
        else:
            rgbas = plt.cm.get_cmap(cmap)(norm(gmap))

There seems to be a bug on some matplotlib compatibility. I used the ugly try-except combo because I am not sure if the condition if mpl_ge_3_6_0()is important in another context. Otherwise I would just remove that.

Congratulations! Is there any thing I should modify in dataframe_image ?

LysSanzMoreta commented 1 year ago

@PaleNeutron Hmm, perhaps recommend a lower version of pandas? like a warning?, I would not enforce a downgrade. Or change the cmap type before feeding it to pandas?

mateuszk098 commented 1 year ago

@LysSanzMoreta I had the same error under pandas 2.1.0. In my case, an update of matplotlib and seaborn to the newest version solved it. So it was related to these libraries, and not the pandas, indeed. Hope this helps.

gumdropsteve commented 1 year ago

I have the same problem with this code: Correlation function itself works well

corr = df.corr(method='spearman', min_periods=3, numeric_only = True)
corr.style.background_gradient(cmap='coolwarm')

I am having this same problem right now. corr is working.

MapleBloom commented 8 months ago

A simple way to solve this problem without editing libraries is just to set "image.cmap" of your choice:

plt.rcParams["image.cmap"] = 'Blues'

and when call 'background_gradient':

.style.background_gradient(cmap=None)
MapleBloom commented 7 months ago

@LysSanzMoreta , sorry not to mention you above! You are right that the problem cause is versioning.

But it is the better way to solve the problem in your code, not in the library https://github.com/dexplo/dataframe_image/issues/74#issuecomment-2015150574.