【问题标题】:Saving a figure after invoking pyplot.show() results in an empty file调用 pyplot.show() 后保存图形会导致一个空文件
【发布时间】:2014-03-19 11:32:03
【问题描述】:

以下示例代码生成一个简单的绘图,然后将其保存到“fig1.pdf”,然后显示它,然后再次将其保存到“fig2.pdf”。第一张图片看起来像预期的那样,但第二张是空白的(包含一个白色方块)。这里到底发生了什么? plt.show() 这条线显然搞砸了,但我不知道是什么/如何!

import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1, 1, 100)
y = x**2
plt.plot(x,y)
plt.savefig('fig1.pdf')
plt.show()
plt.savefig('fig2.pdf')

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    如果要在显示后保存图形,则需要保留图形实例。调用showplt.savefig不起作用的原因是当前的数字已经被重置了。

    pyplot 在幕后跟踪哪些图形、轴等是“当前的”(即尚未与show 一起显示)。 gcfgca get c当前 figure 和当前 axes 实例。 plt.savefig(以及基本上任何其他pyplot 方法)只是做plt.gcf().savefig(...)。换句话说,获取当前图形实例并调用其savefig 方法。同样plt.plot 基本上是plt.gca().plot(...)

    在调用show 后,“当前”图形和轴的列表为空。

    一般来说,最好直接使用图形和轴实例来绘制/保存/显示/等,而不是使用plt.plot 等来隐式获取当前图形/轴并在其上绘制。对所有事情都使用pyplot 没有任何问题(尤其是交互方式),但它更容易让自己在脚下开枪。

    pyplot 用于plt.show() 并生成图形和坐标区对象,然后直接使用图形或坐标区方法。 (例如 ax.plot(x, y) 而不是 plt.plot(x, y) 等)这样做的主要优点是它是明确的。您知道要绘制的对象是什么,并且不必推理 pyplot 状态机的作用(尽管理解状态机接口也不是那么难)。

    作为“推荐”做事方式的示例,请执行以下操作:

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.linspace(-1, 1, 100)
    y = x**2
    
    fig, ax = plt.subplots()
    ax.plot(x, y)
    fig.savefig('fig1.pdf')
    plt.show()
    fig.savefig('fig2.pdf')
    

    如果您更愿意使用pyplot 接口来处理所有事情,那么只需在调用show 之前获取图形实例即可。例如:

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.linspace(-1, 1, 100)
    y = x**2
    
    plt.plot(x, y)
    fig = plt.gcf()
    fig.savefig('fig1.pdf')
    plt.show()
    fig.savefig('fig2.pdf')
    

    【讨论】:

    • +1,乔。这一点,IMO,说明了为什么 pyplot 接口的使用应该保持在最低限度。
    • 加粗 g,c,f 和 g,c,a 以防有人漏掉。从长远来看,它很容易记住 api
    【解决方案2】:

    pyplot.show 在关闭时阻止并破坏情节。你可以使用

    plt.show(block=False)
    

    之后保存到 fig2.pdf 将起作用,或者您可以在保存之前再次绘制它

    plt.plot(x,y)
    plt.savefig('fig2.pdf')
    

    【讨论】:

    • 这不是 block 控制的,因为它的价值。 block 控制 gui 工具包的 mainloop 是否会阻止进一步执行或在单独的线程中运行。
    【解决方案3】:

    在绘制第二个之前,我必须运行 plt.cla()plt.clf()。分别清除当前坐标区和清除当前绘图。

    【讨论】:

      【解决方案4】:

      如果你只是想保存前看图,可以调用

      plt.ion()
      

      在绘图之前,starts interactive modeshows all figures as they are drawn。这主要消除了调用plt.show() 的需要。您不再需要关闭数字即可继续。

      要再次禁用交互模式,请致电plt.ioff()

      【讨论】:

        猜你喜欢
        • 2022-12-04
        • 1970-01-01
        • 1970-01-01
        • 2012-09-08
        • 2021-10-30
        • 1970-01-01
        • 2018-09-30
        • 2022-11-19
        相关资源
        最近更新 更多