在iPython笔记本中动态更新绘图

7

这个问题所述,我正在尝试在iPython笔记本中动态更新绘图(在一个单元格中)。

不同之处在于,我不想绘制新线条,而是我的x_data和y_data在某个循环的每次迭代中都在增长。

我想做的是:

import numpy as np
import time
plt.axis([0, 10, 0, 100]) # supoose I know what the limits are going to be
plt.ion()
plt.show()
x = []
y = []
for i in range(10):
     x = np.append(x, i)
     y = np.append(y, i**2)
     # update the plot so that it shows y as a function of x
     time.sleep(0.5) 

但我希望图表有一个图例,如果这样做

from IPython import display
import time
import numpy as np
plt.axis([0, 10, 0, 100]) # supoose I know what the limits are going to be
plt.ion()
plt.show()
x = []
y = []
for i in range(10):
    x = np.append(x, i)
    y = np.append(y, i**2)
    plt.plot(x, y, label="test")
    display.clear_output(wait=True)
    display.display(plt.gcf())
    time.sleep(0.3)
plt.legend()

我最终得到包含10个项目的图例。如果我把plt.legend()放在循环内,那么在每次迭代中图例都会增加...有什么解决办法吗?

1个回答

7

目前,在循环中每次使用plt.plot时,您都会创建一个新的Axes对象。

因此,如果在使用plt.plot之前清除当前轴(plt.gca().cla()),并将图例放在循环内部,则可以使其正常工作,而不会使图例在每次循环后增长:

import numpy as np
import time
from IPython import display

x = []
y = []
for i in range(10):
    x = np.append(x, i)
    y = np.append(y, i**2)
    plt.gca().cla() 
    plt.plot(x,y,label='test')
    plt.legend()
    display.clear_output(wait=True)
    display.display(plt.gcf()) 
    time.sleep(0.5) 

编辑: 正如@tcaswell在评论中指出的那样,使用%matplotlib notebook魔法命令可以给你一个实时更新和重新绘制的图形。


2
还有一件事:当我运行我的代码片段(添加了你的一行并改变了legend()的位置)后,我得到了两张图片。你有什么想法为什么会这样? - P. Camilleri
1
尝试交换 display.clear_outputdisplay.display 行的顺序。这在你链接到的问题的答案中有更详细的讨论。 - tmdavison
3
如果您使用%matplotlib notebook,您可以做得更好,因为它提供了一个实时的图形界面,您可以对其进行更新和重新绘制(以及平移/缩放和鼠标+键盘事件)。 - tacaswell
@tcaswell:非常好,我不知道%matplotlib notebook。正在更新答案... - tmdavison
1
回复@P. Camilleri的评论:我在循环末尾(或单元格末尾,两种方式都可以)添加了%matplotlib inline作为一种方法来消除第二个图形的出现(当单元格结束时)。交换display.clear_outputdisplay.display的顺序对我没有起作用。我还没有找到正确使用%matplotlib notebook进行动态绘图的方法,因此在此期间这是一种临时解决方案。我在笔记本中的其他地方都使用%matplotlib inline,因此重置它可能对我有意义 :-) - SherylHohman
显示剩余5条评论

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