Saving plots (AxesSubPlot) generated from python pandas with matplotlib's savefig

I'm using pandas to generate a plot from a dataframe, which I would like to save to a file:

dtf = pd.DataFrame.from_records(d,columns=h)
fig = plt.figure()
ax = dtf2.plot()
ax = fig.add_subplot(ax)
fig.savefig('~/Documents/output.png')

It seems like the last line, using matplotlib's savefig, should do the trick. But that code produces the following error:

Traceback (most recent call last):
  File "./testgraph.py", line 76, in <module>
    ax = fig.add_subplot(ax)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/figure.py", line 890, in add_subplot
    assert(a.get_figure() is self)
AssertionError

Alternatively, trying to call savefig directly on the plot also errors out:

dtf2.plot().savefig('~/Documents/output.png')


  File "./testgraph.py", line 79, in <module>
    dtf2.plot().savefig('~/Documents/output.png')
AttributeError: 'AxesSubplot' object has no attribute 'savefig'

I think I need to somehow add the subplot returned by plot() to a figure in order to use savefig. I also wonder if perhaps this has to do with the magic behind the AxesSubPlot class.

EDIT:

the following works (raising no error), but leaves me with a blank page image....

fig = plt.figure()
dtf2.plot()
fig.savefig('output.png')

EDIT 2: The below code works fine as well

dtf2.plot().get_figure().savefig('output.png')

The gcf method is depricated in V 0.14, The below code works for me:

plot = dtf.plot()
fig = plot.get_figure()
fig.savefig("output.png")

You can use ax.figure.savefig(), as suggested in a comment on the question:

import pandas as pd

df = pd.DataFrame([0, 1])
ax = df.plot.line()
ax.figure.savefig('demo-file.pdf')

This has no practical benefit over ax.get_figure().savefig() as suggested in other answers, so you can pick the option you find the most aesthetically pleasing. In fact, get_figure() simply returns self.figure:

# Source from snippet linked above
def get_figure(self):
    """Return the `.Figure` instance the artist belongs to."""
    return self.figure

So I'm not entirely sure why this works, but it saves an image with my plot:

dtf = pd.DataFrame.from_records(d,columns=h)
dtf2.plot()
fig = plt.gcf()
fig.savefig('output.png')

I'm guessing that the last snippet from my original post saved blank because the figure was never getting the axes generated by pandas. With the above code, the figure object is returned from some magic global state by the gcf() call (get current figure), which automagically bakes in axes plotted in the line above.


It seems easy for me that use plt.savefig() function after plot() function:

import matplotlib.pyplot as plt
dtf = pd.DataFrame.from_records(d,columns=h)
dtf.plot()
plt.savefig('~/Documents/output.png')

  • The other answers deal with saving the plot for a single plot, not subplots.
  • In the case where there are subplots, the plot API returns an numpy.ndarray of matplotlib.axes.Axes
import pandas as pd
import seaborn as sns  # for sample data
import matplotlib.pyplot as plt

# load data
df = sns.load_dataset('iris')

# display(df.head())
   sepal_length  sepal_width  petal_length  petal_width species
0           5.1          3.5           1.4          0.2  setosa
1           4.9          3.0           1.4          0.2  setosa
2           4.7          3.2           1.3          0.2  setosa
3           4.6          3.1           1.5          0.2  setosa
4           5.0          3.6           1.4          0.2  setosa

Plot with pandas.DataFrame.plot()

  • The following example uses kind='hist', but is the same solution when specifying something other than 'hist'
  • Use [0] to get one of the axes from the array, and extract the figure with .get_figure().
fig = df.plot(kind='hist', subplots=True, figsize=(6, 6))[0].get_figure()
plt.tight_layout()
fig.savefig('test.png')

enter image description here

Plot with pandas.DataFrame.hist()

1:

  • In this example we assign df.hist to Axes created with plt.subplots, and save that fig.
  • 4 and 1 are used for nrows and ncols, respectively, but other configurations can be used, such as 2 and 2.
fig, ax = plt.subplots(nrows=4, ncols=1, figsize=(6, 6))
df.hist(ax=ax)
plt.tight_layout()
fig.savefig('test.png')

enter image description here

2:

  • Use .ravel() to flatten the array of Axes
fig = df.hist().ravel()[0].get_figure()
plt.tight_layout()
fig.savefig('test.png')

enter image description here