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

6

140

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')
Bowline answered 24/10, 2013 at 1:55 Comment(0)
K
168

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")
Kolb answered 10/7, 2014 at 10:51 Comment(0)
A
44

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
Antifreeze answered 22/1, 2020 at 12:23 Comment(0)
B
20

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.

Bowline answered 24/10, 2013 at 2:11 Comment(0)
I
15

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')
Iphigeniah answered 27/2, 2016 at 11:7 Comment(0)
D
15
  • 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

Demonstrable answered 21/4, 2021 at 19:5 Comment(2)
.get_figure() was what I was looking for. ThanksDistance
The method with .ravel() was the most suitable to be used with KedroCabbala
D
4

this may be a simpler approach:

(DesiredFigure).get_figure().savefig('figure_name.png')

i.e.

dfcorr.hist(bins=50).get_figure().savefig('correlation_histogram.png')
Damnedest answered 22/2, 2019 at 18:14 Comment(2)
can you please add some more explanation with an example?Nerissa
this doesn't work if you are creating multiple figures within the same function (but does work in jupyter notebook cells).Whiffet

© 2022 - 2024 — McMap. All rights reserved.