Pandas: ValueError plotting bar plot from DataFrame with existing Axes

Created on 24 Aug 2016  ·  3Comments  ·  Source: pandas-dev/pandas

Code Sample, a copy-pastable example if possible

The following code works, and when pasted in a Jupyter Notebook or QT console yields the expected bar plot:

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt

# Create some data to plot
df = pd.DataFrame(
        dict(Feature1=[10, 20, 30, 20, 10], Feature2=[3, 2, 3, 2, 3]),
        index=['a', 'b', 'c', 'd', 'e']
)
_ = df.plot(kind='bar', legend=False, y='Feature1', yerr='Feature2', rot=0)

However, as soon as I try to supply a custom Axes instance (so the plot gets put where I want it), it throws an error. Running the following code after the above example throws an error:

fig = plt.figure(0)
ax = fig.add_subplot(111)
_ = df.plot(kind='bar', legend=False, y='Feature1', yerr='Feature2', rot=0, axes=ax)

Here is the traceback:

Traceback (most recent call last):
  File "<stdin>", line 12, in <module>
  File "/usr/local/miniconda3/lib/python3.5/site-packages/pandas/tools/plotting.py", line 3740, in __call__
    sort_columns=sort_columns, **kwds)
  File "/usr/local/miniconda3/lib/python3.5/site-packages/pandas/tools/plotting.py", line 2614, in plot_frame
    **kwds)
  File "/usr/local/miniconda3/lib/python3.5/site-packages/pandas/tools/plotting.py", line 2441, in _plot
    plot_obj.generate()
  File "/usr/local/miniconda3/lib/python3.5/site-packages/pandas/tools/plotting.py", line 1028, in generate
    self._make_plot()
  File "/usr/local/miniconda3/lib/python3.5/site-packages/pandas/tools/plotting.py", line 1971, in _make_plot
    log=self.log, **kwds)
  File "/usr/local/miniconda3/lib/python3.5/site-packages/pandas/tools/plotting.py", line 1918, in _plot
    return ax.bar(x, y, w, bottom=start, log=log, **kwds)
  File "/usr/local/miniconda3/lib/python3.5/site-packages/matplotlib/__init__.py", line 1812, in inner
    return func(ax, *args, **kwargs)
  File "/usr/local/miniconda3/lib/python3.5/site-packages/matplotlib/axes/_axes.py", line 2134, in bar
    self.add_patch(r)
  File "/usr/local/miniconda3/lib/python3.5/site-packages/matplotlib/axes/_base.py", line 1780, in add_patch
    self._set_artist_props(p)
  File "/usr/local/miniconda3/lib/python3.5/site-packages/matplotlib/axes/_base.py", line 865, in _set_artist_props
    a.axes = self
  File "/usr/local/miniconda3/lib/python3.5/site-packages/matplotlib/artist.py", line 237, in axes
    raise ValueError("Can not reset the axes.  You are "
ValueError: Can not reset the axes.  You are probably trying to re-use an artist in more than one Axes which is not supported

Expected Output

I would expect the second plot to work identically to the first plot in this example.

output of pd.show_versions()

INSTALLED VERSIONS
------------------
commit: None
python: 3.5.2.final.0
python-bits: 64
OS: Linux
OS-release: 4.4.6-gentoo
machine: x86_64
processor: Intel(R) Core(TM) i3-3240 CPU @ 3.40GHz
byteorder: little
LC_ALL: None
LANG: en_US.utf8

pandas: 0.18.1
nose: 1.3.7
pip: 8.1.2
setuptools: 25.1.6
Cython: None
numpy: 1.11.1
scipy: 0.18.0
statsmodels: 0.6.1
xarray: None
IPython: 5.1.0
sphinx: 1.4.1
patsy: 0.4.1
dateutil: 2.5.3
pytz: 2016.6.1
blosc: None
bottleneck: None
tables: 3.2.3.1
numexpr: 2.6.1
matplotlib: 1.5.1
openpyxl: None
xlrd: 1.0.0
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: None
httplib2: None
apiclient: None
sqlalchemy: 1.0.13
pymysql: None
psycopg2: 2.6.1 (dt dec pq3 ext)
jinja2: 2.8
boto: None
pandas_datareader: None

(FWIW, I just built and tried the latest version of pandas and got the same behavior:

pandas: 0.18.1+391.g6645b2b

)

Usage Question

Most helpful comment

You want to use ax=ax, not axes.

Unfortunately, I don't think there's much we can do to catch this kind of errors. We accept **kwargs in the .plot methods, and pass them along to the underlying matplotlib method (e.g. .ax.bar). I'm not really sure why matplotlib axes.bar accepts an axes keyword, presumably for compatibility with the pylab interface?

All 3 comments

You want to use ax=ax, not axes.

Unfortunately, I don't think there's much we can do to catch this kind of errors. We accept **kwargs in the .plot methods, and pass them along to the underlying matplotlib method (e.g. .ax.bar). I'm not really sure why matplotlib axes.bar accepts an axes keyword, presumably for compatibility with the pylab interface?

I'm going to close this for now; we could potentially accept axes as an alias for ax (not sure why ax was chosen originally), but I'd say hold off for now and see if more people run into this.

Ack. Thanks!

Was this page helpful?
0 / 5 - 0 ratings