我正在编写一个快速脚本来动态生成绘图。我使用下面的代码(来自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)中,以便例如可以在批处理脚本中使用。我该怎么办?

评论

看来我找到了答案:它的pylab.savefig('foo.png')

链接应该链接到matplotlib.org中的某个地方吗?

另外,如果不使用pylab,则Figure对象也具有savefig方法。因此,您可以调用fig = plt.figure()然后调用fig.savefig(...)。

页面下方的许多答案都提到plt.close(fig),这在大循环中尤其重要。否则,数字将保持打开状态并在内存中等待,并且在执行plt.show()
时将显示所有打开的数字
nb:首选matplotlib.pyplot:stackoverflow.com/questions/11469336/…

#1 楼

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

from matplotlib import pyplot as plt

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


将分别给出光栅化或矢量化的输出,这两者都可能有用。另外,您会发现pylab在图像周围留有大量的空白,通常是不希望的。使用以下方法将其删除:

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


评论


是否可以更改生成图像的尺寸?

–拉马吉登
13-10-28在21:15

@Asmageddon在plt.savefig中,您可以更改dpi,请参见答案中的链接。创建图形时可以控制尺寸,请参见matplotlib.org/api/figure_api.html#matplotlib.figure.Figure中的figsize。

–钩了
13-10-29在0:46



@MoTSCHIGGE,您可以调用plt.ioff(),该命令应禁用matplotlib.pyplot命令中的交互性。

– rubenvb
2015年12月10日上午8:25

@STMohammed foo.png是路径。例如,您可以将其放在类似savefig(“ mydir / foo.png”)的目录中。

–钩了
18年8月3日在13:56

bbox_inches ='tight'就像一个饰物。你让我今天一整天都感觉很好

–猫建物
19-10-3在8:34

#2 楼

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

但是我发现在某些情况下始终可以显示该图。 (例如,使用Spyder的plt.ion():交互模式=开。)我通过用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


如果需要,您应该可以稍后重新打开该图(不要测试自己)。

评论


您还可以设置plt.ioff()#轮换使用交互式绘图模式,但是如果代码退出并出现错误,则可能会禁用您要使用的行为。

– Demis
15年12月14日在19:04

您将在Jupyter笔记本电脑中看到相同的问题。 plt.close(fig)解决了

– insco
19年7月15日在14:21

您能解释一下什么是斧头,无花果和鸭嘴兽吗?使用这些总是让我感到困惑。

–随机确定性
6月8日21:25

plt只是matplotlib.pyplot的别名,以使其易于键入。查找帮助(plt.subplots)以查看返回的内容-我的代码注释,一个Figure对象和一个Axis对象中也提到了此内容。

– Demis
6月10日0:20

请注意,名称ax / fig / plt由变量名组成-可以随意命名。无论哪种方式,它们都包含对象。您可以在此处查看子图返回哪些对象:matplotlib.org/3.2.1/api/_as_gen/…,以及pyplot模块在此处:matplotlib.org/tutorials/introductory/pyplot.html。

– Demis
6月28日22:45



#3 楼

解决方案是:

pylab.savefig('foo.png')


#4 楼

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

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

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


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

UPDATE:对于Spyder,您通常无法以这种方式设置后端(因为Spyder通常会加载请尽早使用matplotlib,以防止您使用matplotlib.use())。相反,请使用plt.switch_backend('Agg')或在Spyder首选项中关闭“启用支持”并自己运行matplotlib.use('Agg')命令。

来自这两个提示:一,二

评论


这对于没有固定显示的情况非常有效。如果os.environ ['DISPLAY']的设置不正确,则将另一个后端与.plot()一起使用将引发错误。

–经济
18年5月30日在18:23

谢谢。这对没有互联网连接并且需要系统管理员安装任何软件包的生产服务器非常有用。

–里昂
18年11月11日在6:48

我喜欢matplotlib网站上有关“后端”的描述/定义的教程:matplotlib.org/tutorials/introductory/…

– Tanner Strunk
5月30日16:52

#5 楼

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

import matplotlib.image as mpimg

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


评论


这不只是将src.png复制到out.png吗?

– Gerrit
16年5月26日在11:44

这只是一个示例,它显示了是否有图像对象(img),然后可以使用.imsave()方法将其保存到文件中。

– wonder.mice
16年5月26日在23:29

@ wonder.mice将有助于显示如何在不使用当前图形的情况下创建图像。

– scry
16年8月10日在6:50

@ wonder.mice感谢本示例,它是第一个向我展示如何将图像对象保存为.png的示例。

– Arthur Dent
17年5月24日在21:09

@scry您并非总是需要创建图像,有时您需要尝试一些代码并希望获得视觉输出,在这种情况下它很方便。

–Schütze
19-2-13在15:08



#6 楼

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()


#7 楼

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

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


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

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

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

评论


用数字内联在Jupyter笔记本中进行开发会不会更容易?这样,您就可以准确跟踪历史记录,甚至可以重新运行它。

–西门人Tomoiagă
17年4月4日在14:55

@CiprianTomoiaga我从不从交互式Python shell(Jupyter或其他)生成生产图。我从脚本中绘制所有内容。

– Gerrit
17-12-5 '23:42

#8 楼

使用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()


评论


有人说fig = plt.figure(figuresize = 4,5)可能是fig = plt.figure(figsize =(4,5))#figure尺寸以英寸为单位

–用户
19年1月13日在12:32

#9 楼

我使用了以下命令:

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中导出图

评论


抱歉,这是什么?绘制的图像文件? f = plt.savefig('data.png')

–莫尔斯
18年4月4日在13:48

#10 楼

您可以执行以下操作之一:

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')


评论


出现了意外的关键字参数“ hold”

– amitdatta
17年12月6日在1:36

#11 楼

如果像我一样使用Spyder IDE,则必须使用以下命令禁用交互模式:

plt.ioff()

(此命令在科学启动时自动启动)

如果要再次启用它,请使用:

plt.ion()

#12 楼

解决方案:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
plt.figure()
ts.plot()
plt.savefig("foo.png", bbox_inches='tight')


如果要显示图像并保存图像,请使用:

%matplotlib inline



import matplotlib

#13 楼

根据问题Matplotlib(pyplot)savefig输出空白图像。

应注意一件事:如果使用plt.show且应在plt.savefig之后,否则将给出空白图像。

详细示例:

import numpy as np
import matplotlib.pyplot as plt


def draw_result(lst_iter, lst_loss, lst_acc, title):
    plt.plot(lst_iter, lst_loss, '-b', label='loss')
    plt.plot(lst_iter, lst_acc, '-r', label='accuracy')

    plt.xlabel("n iteration")
    plt.legend(loc='upper left')
    plt.title(title)
    plt.savefig(title+".png")  # should before plt.show method

    plt.show()


def test_draw():
    lst_iter = range(100)
    lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
    # lst_loss = np.random.randn(1, 100).reshape((100, ))
    lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
    # lst_acc = np.random.randn(1, 100).reshape((100, ))
    draw_result(lst_iter, lst_loss, lst_acc, "sgd_method")


if __name__ == '__main__':
    test_draw()




#14 楼

import matplotlib.pyplot as plt
plt.savefig("image.png")


在Jupyter Notebook中,您必须删除plt.show()并添加plt.savefig()以及其他plt代码在一个单元格中。
图像仍将显示在笔记本中。 />

#15 楼

使用matplotlib.pyplot时,必须先保存您的绘图,然后使用以下两行将其关闭:

fig.savefig('plot.png') # save the plot, place the path you want to save the figure in quotation
plt.close(fig) # close the figure window


#16 楼

除上述内容外,我还添加了__file__作为名称,以便图片和Python文件获得相同的名称。我还添加了一些参数使它看起来更好:

# Saves a PNG file of the current graph to the folder and updates it every time
# (nameOfimage, dpi=(sizeOfimage),Keeps_Labels_From_Disappearing)
plt.savefig(__file__+".png",dpi=(250), bbox_inches='tight')
# Hard coded name: './test.png'


#17 楼

鉴于今天(提出此问题时不可用)很多人使用Jupyter Notebook作为python控制台,有一种极其简单的方法将图保存为.png,只需从Jupyter Notebook调用matplotlibpylab类,绘制图即可。图“内联” jupyter单元格,然后将该图/图像拖到本地目录。不要忘记第一行中的
%matplotlib inline

评论


这是一个好主意,只要将图像保留在笔记本中,只需注意对文件大小的影响。

– prusswan
18/12/29在17:28

#18 楼

如之前建议的那样,您可以使用:

import matplotlib.pyplot as plt
plt.savefig("myfig.png")


保存所显示的任何IPhython图像。或者换个角度看(从另一个角度看),如果您曾经使用过开放式简历,或者如果您已导入开放式简历,则可以进行以下操作:

导入cv2

cv2.imwrite(“ myfig.png”,image)

但是,这是万一情况,如果您需要使用Open CV。否则,plt.savefig()应该足够。

#19 楼

您可以使用任何扩展名(png,jpg等)并以所需的分辨率保存图像。这是保存您的身材的功能。

import os

def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
    path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
    print("Saving figure", fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format=fig_extension, dpi=resolution)


'fig_id'是您想要保存图形的名称。希望对您有所帮助:)

#20 楼

您可以这样操作:

def plotAFig():
  plt.figure()
  plt.plot(x,y,'b-')
  plt.savefig("figurename.png")
  plt.close()