MatPlotLib的ion()和draw()不起作用

9

我正在尝试使用for循环实时绘制图形。 我有以下简单的代码:

import matplotlib.pyplot as plt

plt.ion()
plt.figure()
for i in range(100):
    plt.plot([i], [i], 'o')
    plt.draw()
    plt.pause(0.0001)

这段代码在计算完成前不会显示图形,这不是我想要的。我希望它可以在每次循环之后绘制图形。如果将plt.draw()替换为plt.show,则可以实时输出多个图形,但我希望它们都出现在同一张图中。有什么想法吗?
编辑:
我下载了带有Anaconda的PyCharm,一切正常。我猜这是Spyder的问题,因为我尝试过几个不同版本的Spyder,但没有成功。如果有人知道在Spyder中引起此问题的原因,请告诉我!

尝试在 plt.figure() 后加上 plt.show() - Ben
这样做,我会得到输出 <matplotlib.figure.Figure at 0xa4e77f0>,代码的评估与 - Alex
你是如何执行脚本的?是从bash终端调用python script.py吗?还是在Ipython终端内部调用%run - Ben
这不是典型的行为。你所拥有的应该可以工作。尝试通过Ipython运行它(https://pythonhosted.org/spyder/ipythonconsole.html)。如果那样不起作用,可能是图形后端的问题(https://dev59.com/KnA75IYBdhLWcg3wdIz7)。 - Ben
我不使用Spyder,所以很遗憾,我无法提供太多帮助。我在使用其他软件包时遇到了类似的问题,现在我通过命令行运行IPython来避免一些问题。您可以尝试自定义matplotlibrc文件(http://matplotlib.org/1.4.0/users/customizing.html),以便在加载到Spyder之前设置后端。 - Ben
显示剩余3条评论
4个回答

7

这段内容从Python实时绘图中为您定制。

import matplotlib.pyplot as plt
import numpy as np
import time

fig = plt.figure()
ax = fig.add_subplot(111)

# some X and Y data
x = [0]
y = [0]

li, = ax.plot(x, y,'o')

# draw and show it
fig.canvas.draw()
plt.show(block=False)

# loop to update the data
for i in range(100):
    try:
        x.append(i)
        y.append(i)

        # set the new data
        li.set_xdata(x)
        li.set_ydata(y)

        ax.relim() 
        ax.autoscale_view(True,True,True) 

        fig.canvas.draw()

        time.sleep(0.01)
    except KeyboardInterrupt:
        plt.close('all')
        break

谢谢回复。我尝试运行您的代码,但是出现错误,显示“show()”有一个意外的参数。我读到块参数是实验性的,但我不确定为什么它在我的Spyder平台上无法工作。 - Alex
жІЎжңүдҪҝз”Ёblockе…ій”®еӯ—дјҡиө·дҪңз”Ёеҗ—пјҹжҳҫ然пјҢеҰӮжһңжӮЁе·Із»ҸеӨ„дәҺдәӨдә’жЁЎејҸпјҢеҲҷдёҚиө·дҪңз”ЁгҖӮ - CoMartel
没有使用 block 语句也可以工作,但是这样会输出许多不同的数字。有没有一种方法可以把它们全部放在一起? - Alex
这似乎是一个特定于Spyder的问题,因为在我的电脑上它完美地工作。我对Spyder不够熟悉,无法帮助你。 - CoMartel
time.sleep() 对我无效,但是使用 plt.pause() 可以解决问题。 - d.popov
1
谢谢!这是一个最终让我成功的例子。初始尝试并不成功,但我没有想到 ax.relim() 和 ax.autoscale_view(True,True,True) 这两行很重要。在添加它们之后,它就起作用了。 - Matiss Zuravlevs

4

这个解决方案的例子在多台机器上都适用。尝试调整 plt.pause(...)

import matplotlib.pyplot as plt
import numpy as np

F = lambda x: np.sin(2*x)

plt.ion()    
x = np.linspace(0, 1, 200)
plt.plot(x, F(x))


for i in range(100):
    if 'ax' in globals(): ax.remove()
    newx = np.random.choice(x, size = 10)
    ax = plt.scatter(newx, F(newx))
    plt.pause(0.05)

plt.ioff()
plt.show()

3

嘿,我遇到了同样的问题。我查看了其他相关的问题,并在我的解决方案中加入了暂停,问题得到了解决。下面是一些对我有效的示例代码。

import matplotlib.pyplot as plt
import numpy as np
plt.ion()
x = np.arange(0, 4*np.pi, 0.1)
y = [np.sin(i) for i in x]
plt.plot(x, y, 'g-', linewidth=1.5, markersize=4)
plt.pause(0.0001)         
plt.plot(x, [i**2 for i in y], 'g-', linewidth=1.5, markersize=4)
plt.pause(0.0001)
plt.plot(x, [i**2*i+0.25 for i in y], 'r-', linewidth=1.5, markersize=4) 
plt.pause(0.0001)

解决方案已发布在此处:Matplotlib ion() and subprocesses

plt.pause() 而不是 time.sleep() 对我也起作用了。 - d.popov

1
问题和解决方案高度依赖于Python环境和后端中的plot.draw()函数,甚至可能因不同产品版本而有所不同。它在不同的环境下表现出不同的方式。该问题在stackoverflow上出现了许多次,其中一些解决方案适用于某些人,但对其他人则无效。
在我的Windows笔记本电脑上,最好的方法是从命令行运行Python - 没有IDE,只是纯粹的Python3。如示例中所示,draw()总是能正常工作。
如果我在同一台机器上尝试在Jupyter笔记本中执行此操作,则无论是使用draw()、plot.pause()、plot.show()还是任何其他建议都无法绘制图形。我尝试了%matplotlib与notebook、widget和ipympl。在完全执行单元格代码之前,什么也没有被绘制出来。
stackoverflow上的其他一些来源建议使用figure.canvas.flush_events()。我在这方面取得了一些成功并进行了进一步的调查。
最好的解决方案是在figure.canvas级别而不是axes或plot级别运行draw()。
您可以通过使用以下命令创建您的绘图来获取figure:
fig, graph, = plt.subplots()

如果您已经创建了情节,就像票证顶部的代码一样,请将以下内容放在循环之外:
fig = plt.gcf() #get current figure

在循环内部,使用以下代码而不是plt.draw():
fig.canvas.draw()

在我的Jupyter Notebook环境中,即使在多个图形和绘图轴上运行,它也被证明是可靠的。我可以插入sleep()语句,一切都按预期出现。
你的情况可能会有所不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接