Pandas: plotting in pandas is not picking the list of colors passed, it only gets the first value

Created on 4 Jul 2017  Â·  13Comments  Â·  Source: pandas-dev/pandas

Code Sample, a copy-pastable example if possible

>>> df = pd.DataFrame({"A": range(4), "color": ['red', 'blue', 'blue', 'red']})
>>> ax = df.plot.bar(y='A', color=df['color'])
>>> [p.get_facecolor() for p in ax.patches]
[(1.0, 0.0, 0.0, 1.0),
 (1.0, 0.0, 0.0, 1.0),
 (1.0, 0.0, 0.0, 1.0),
 (1.0, 0.0, 0.0, 1.0)]

Problem description

It plots correctly but it does not pick the right color per bar. it only pick the color of the first value in the list.
it was working perfectly in pandas 0.19.2

Expected Output

the plot should contain a different color as the list is being passed. Similar to matplotlib behavior and the old pandas version

Output of pd.show_versions()

pandas: 0.20.2
pytest: None
pip: 9.0.1
setuptools: 36.0.1
Cython: None
numpy: 1.12.1
scipy: 0.19.1
xarray: None
IPython: 5.4.1
sphinx: None
patsy: None
dateutil: 2.6.0
pytz: 2017.2
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 2.0.2
openpyxl: None
xlrd: 1.0.0
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: 0.9999999
sqlalchemy: None
pymysql: None
psycopg2: 2.7.1 (dt dec pq3 ext lo64)
jinja2: 2.9.6
s3fs: None
pandas_gbq: None
pandas_datareader: None

Regression Visualization

Most helpful comment

I'm still facing this issue...

All 13 comments

I left a comment on #14757 which seems to be the culprit.

14757 looks unrelated, that was for .style, not .plot. PRs welcome if you want to take a look.

The problem seems to be in _get_colors. I think that BarPlot should define a _get_colors that does something like

```python
def _get_colors(self, num_colors=None, color_kwds='color'):
color = self.kwds.get('color')
if color is None:
return super()._get_colors(self, num_colors=num_colors, color_kwds=color_kwds)
else:
num_colors = len(self.data) # maybe? may not work for some cases
return _get_standard_colors(color=kwds.get('color'), num_colors=num_colors)
````

will need tests and stuff too.

@TomAugspurger This a regression bug that can crash matplotlib(see below). I think this might be a bigger deal than "next major release"

If you give a color as an RGB or RGBA tuple the dataframe plot command only forwards the first number and this(a single float) isn't a valid color so matplotlib crashes and plots a blank(broken really) graph.

user@user-comp:~$ ipython --pylab
Python 3.6.0 |Anaconda custom (64-bit)| (default, Dec 23 2016, 12:22:00) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.
Using matplotlib backend: Qt5Agg

In [1]: import pandas as pd

In [2]: pd.__version__
Out[2]: '0.20.2'

In [3]: df = pd.DataFrame({"A": range(10)})

In [4]: df.plot(y='A', color=(0.3,0.4,0.4,1))
Out[4]: <matplotlib.axes._subplots.AxesSubplot at 0x7f90dbdea160>

In [5]: Traceback (most recent call last):
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/colors.pa
    rgba = _colors_full_map.cache[c, alpha]
KeyError: (0.3, None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/backendsg
    FigureCanvasAgg.draw(self)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/backendsw
    self.figure.draw(self.renderer)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/artist.pr
    draw(artist, renderer, *args, **kwargs)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/figure.pw
    renderer, self, dsu, self.suppressComposite)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/image.pys
    a.draw(renderer)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/artist.pr
    draw(artist, renderer, *args, **kwargs)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_baw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/image.pys
    a.draw(renderer)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/artist.pr
    draw(artist, renderer, *args, **kwargs)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/lines.pyw
    ln_color_rgba = self._get_rgba_ln_color()
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/lines.pyr
    return mcolors.to_rgba(self._color, self._alpha)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/colors.pa
    rgba = _to_rgba_no_colorcycle(c, alpha)
  File "/home/user/anaconda3/lib/python3.6/site-packages/matplotlib/colors.pe
    raise ValueError("Invalid RGBA argument: {!r}".format(orig_c))
ValueError: Invalid RGBA argument: 0.3

works fine on 0.19

user@user-comp:~$ ipython --pylab
Python 3.6.0 |Anaconda custom (64-bit)| (default, Dec 23 2016, 12:22:00) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.
Using matplotlib backend: Qt5Agg

In [1]: import pandas as pd

In [2]: pd.__version__
Out[2]: '0.19.2'

In [3]: df = pd.DataFrame({"A": range(10)})

In [4]: df.plot(y='A', color=(0.3,0.4,0.4))
Out[4]: <matplotlib.axes._subplots.AxesSubplot at 0x7fa95e159710>

In [5]: 

@TomAugspurger This a regression bug that can crash matplotlib(see below). I think this might be a bigger deal than "next major release"

@bcolsen certainly a patch is welcome. We have 1900 issues, how does one prioritize?

The next minor release is tomorrow, so you may not have time to get a PR in.

On Jul 6, 2017, at 05:08, Jeff Reback notifications@github.com wrote:

@TomAugspurger This a regression bug that can crash matplotlib(see below). I think this might be a bigger deal than "next major release"

@bcolsen certainly a patch is welcome. We have 1900 issues, how does one prioritize?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@jreback Sorry for the bug triage suggestion...I clearly have no idea what your release scheduled is like.

I can't get a PR in by tomorrow, but will have a look at it. This is what i have so far.

Initially this line, seems to be the problem:

colors = list(color) if is_list_like(color) else color

https://github.com/pandas-dev/pandas/blob/9e55af2552664267ce27c7fc6c932acb0651c259/pandas/plotting/_style.py#L100

but this code is in plotting.py in 0.19 and it works fine.

The difference is in 0.19 _get_standard_colors gets the color tuple wrapped as a list already so line 100 does:

[(0.3, 0.4, 0.4)] ->  [(0.3, 0.4, 0.4)]

in 0.20 _get_standard_colors gets just the tuple. So it does this.

(0.3, 0.4, 0.4) ->  [0.3, 0.4, 0.4]

Any update?

I have a work around for people being affected by this:

Plot with color in an extra list:

df.plot(y='A', color=[(0.3,0.4,0.4,1)])

also fixes bar:

>>> df = pd.DataFrame({"A": range(4), "color": ['red', 'blue', 'blue', 'red']})
>>> ax = df.plot.bar(y='A', color=[df['color']])
>>> [p.get_facecolor() for p in ax.patches]
Out[35]: 
[(1.0, 0.0, 0.0, 1.0),
 (0.0, 0.0, 1.0, 1.0),
 (0.0, 0.0, 1.0, 1.0),
 (1.0, 0.0, 0.0, 1.0)]

I'm still facing this issue...

I am still facing the same issue. Why is this closed?

https://github.com/pandas-dev/pandas/pull/17360 fixed this. It's possible that there was a regression, or you're getting the same error message from a different case. Either way, @senjed / @adesorme can you open a new issue with an example demonstrating the problem?

Was this page helpful?
0 / 5 - 0 ratings