将绘图保存到图像文件,而不是使用 Matplotlib 显示

我正在编写一个快速脚本来动态生成绘图。我使用下面的代码(来自Matplotlib文档)作为起点:

from pylab import figure, axes, pie, title, show

# Make a square figure and axes
figure(1, figsize=(6, 6))
ax = axes([0.1, 0.1, 0.8, 0.8])

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15, 30, 45, 10]

explode = (0, 0.05, 0, 0)
pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True)
title('Raining Hogs and Dogs', bbox={'facecolor': '0.8', 'pad': 5})

show()  # Actually, don't show, just save to foo.png

我不想将图形显示在 GUI 上,而是要将图形保存到文件(例如 foo.png)中,以便可以在批处理脚本中使用它。我怎么做?

答案

在回答问题后,我想在使用matplotlib.pyplot.savefig时添加一些有用的提示。文件格式可以通过扩展名指定:

from matplotlib import pyplot as plt

plt.savefig('foo.png')
plt.savefig('foo.pdf')

将分别给出栅格化或矢量化的输出,这两个都可能有用。此外,您会发现pylab在图像周围留有大量的空白,通常是不希望有的空白。删除它:

savefig('foo.png', bbox_inches='tight')

正如其他人所说, plt.savefig()fig1.savefig()确实是保存图像的方法。

但是我发现在某些情况下总是显示该图 。 (例如,具有 Spyder 的。 plt.ion()交互模式 = ON)我变通的作法迫使图窗口的关闭在我的巨环plt.close(figure_object)文档 ),所以我不” 在循环中没有一百万个开放数字:

import matplotlib.pyplot as plt
fig, ax = plt.subplots( nrows=1, ncols=1 )  # create figure & 1 axis
ax.plot([0,1,2], [10,20,3])
fig.savefig('path/to/save/image/to.png')   # save the figure to file
plt.close(fig)    # close the figure window

如果需要与您应该能够在以后重新打开图fig.show()没有测试自己)。

解决方案是:

pylab.savefig('foo.png')

刚在 MatPlotLib 文档中找到此链接,正是此链接可解决此问题: http ://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

他们说,防止图形弹出的最简单方法是通过matplotib.use(<backend>)使用非交互式后端(例如 Agg matplotib.use(<backend>) ,例如:

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('myfig')

我个人仍然更喜欢使用plt.close( fig ) ,因为从那时起,您可以选择隐藏某些图形(在循环过程中),但仍显示图形以进行循环后数据处理。不过,它可能比选择非交互式后端要慢 - 如果有人对此进行了测试,那将很有趣。

更新 :对于 Spyder,通常不能以这种方式设置后端(因为 Spyder 通常会提早加载 matplotlib,从而阻止您使用matplotlib.use() )。

而是使用plt.switch_backend('Agg') ,或在 Spyder 首选项中关闭 “ 启用支持 ”,然后自己运行matplotlib.use('Agg')命令。

从这两个提示:

如果您不喜欢 “当前” 数字的概念,请执行以下操作:

import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)

其他答案是正确的。但是,有时我发现我想稍后再打开图形对象 。例如,我可能想更改标签大小,添加网格或进行其他处理。在理想的情况下,我只需要重新运行生成图的代码并修改设置即可。 las,世界并不完美。因此,除了保存为 PDF 或 PNG 之外,我还添加:

with open('some_file.pkl', "wb") as fp:
    pickle.dump(fig, fp, protocol=4)

这样,以后可以加载图形对象并根据需要操纵设置。

我还为堆栈中的每个函数 / 方法写了带有源代码和locals()字典的堆栈,以便以后可以准确地知道是什么产生了该图。

注意:请小心,因为有时此方法会生成巨大的文件。

使用 plot()和其他函数创建所需的内容之后,可以使用如下子句在打印到屏幕或文件之间进行选择:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(4, 5))       # size in inches
# use plot(), etc. to create your plot.

# Pick one of the following lines to uncomment
# save_file = None
# save_file = os.path.join(your_directory, your_file_name)  

if save_file:
    plt.savefig(save_file)
    plt.close(fig)
else:
    plt.show()
import datetime
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt

# Create the PdfPages object to which we will save the pages:
# The with statement makes sure that the PdfPages object is closed properly at
# the end of the block, even if an Exception occurs.
with PdfPages('multipage_pdf.pdf') as pdf:
    plt.figure(figsize=(3, 3))
    plt.plot(range(7), [3, 1, 4, 1, 5, 9, 2], 'r-o')
    plt.title('Page One')
    pdf.savefig()  # saves the current figure into a pdf page
    plt.close()

    plt.rc('text', usetex=True)
    plt.figure(figsize=(8, 6))
    x = np.arange(0, 5, 0.1)
    plt.plot(x, np.sin(x), 'b-')
    plt.title('Page Two')
    pdf.savefig()
    plt.close()

    plt.rc('text', usetex=False)
    fig = plt.figure(figsize=(4, 5))
    plt.plot(x, x*x, 'ko')
    plt.title('Page Three')
    pdf.savefig(fig)  # or you can pass a Figure object to pdf.savefig
    plt.close()

    # We can also set the file's metadata via the PdfPages object:
    d = pdf.infodict()
    d['Title'] = 'Multipage PDF Example'
    d['Author'] = u'Jouni K. Sepp\xe4nen'
    d['Subject'] = 'How to create a multipage pdf file and set its metadata'
    d['Keywords'] = 'PdfPages multipage keywords author title subject'
    d['CreationDate'] = datetime.datetime(2009, 11, 13)
    d['ModDate'] = datetime.datetime.today()

我使用了以下内容:

import matplotlib.pyplot as plt

p1 = plt.plot(dates, temp, 'r-', label="Temperature (celsius)")  
p2 = plt.plot(dates, psal, 'b-', label="Salinity (psu)")  
plt.legend(loc='upper center', numpoints=1, bbox_to_anchor=(0.5, -0.05),        ncol=2, fancybox=True, shadow=True)

plt.savefig('data.png')  
plt.show()  
f.close()
plt.close()

保存数字后,我发现使用 plt.show 非常重要,否则它将无法正常工作。 图导出为 png

您可以执行以下操作:

plt.show(hold=False)
plt.savefig('name.pdf')

并记得在关闭 GUI 图之前先让 savefig 完成。这样,您可以预先查看图像。

或者,您可以使用plt.show()查看它,然后关闭 GUI 并再次运行脚本,但是这次将plt.show()替换为plt.savefig()

或者,您可以使用

fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')