关于python:如何动态更新ipython笔记本中循环中的绘图(在一个单元格内)

how to dynamically update a plot in a loop in ipython notebook (within one cell)

环境:Python 2.7,matplotlib 1.3,IPython笔记本1.1,linux,chrome。代码在一个输入单元格中,使用--pylab=inline

我想使用IPython笔记本和pandas来消耗流并每5秒动态更新一次。

当我只使用print语句以文本格式打印数据时,它完全正常:输出单元格只保留打印数据并添加新行。但是当我尝试绘制数据(然后在循环中更新它)时,绘图永远不会出现在输出单元格中。但如果我删除循环,只需绘制一次。它工作正常。

然后我做了一些简单的测试:

1
2
3
4
5
i = pd.date_range('2013-1-1',periods=100,freq='s')
while True:
    plot(pd.Series(data=np.random.randn(100), index=i))
    #pd.Series(data=np.random.randn(100), index=i).plot() also tried this one
    time.sleep(5)

在手动中断进程(ctrl + m + i)之前,输出不会显示任何内容。在我打断它之后,该图正确地显示为多个重叠的行。但我真正想要的是一个每5秒显示并更新一次的情节(或者每当调用plot()函数时,就像我上面提到的打印语句输出一样,效果很好)。仅在单元格完成后才显示最终图表不是我想要的。

我甚至尝试在每个plot()之后显式添加draw()函数,等等。它们都不起作用。想知道如何通过IPython笔记本中一个单元格内的for / while循环动态更新绘图。


使用IPython.display模块:

1
2
3
4
5
6
7
8
9
%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
    pl.plot(pl.randn(100))
    display.clear_output(wait=True)
    display.display(pl.gcf())
    time.sleep(1.0)


您可以通过将wait=True添加到clear_output来进一步改进:

1
2
display.clear_output(wait=True)
display.display(pl.gcf())


关于HYRY的答案有几点改进:

  • clear_output之前调用display,以便在单元格中断时最终得到一个图,而不是两个图。
  • 捕获KeyboardInterrupt,以便单元格输出不会跟踪回溯。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import matplotlib.pylab as plt
import pandas as pd
import numpy as np
import time
from IPython import display
%matplotlib inline

i = pd.date_range('2013-1-1',periods=100,freq='s')

while True:
    try:
        plt.plot(pd.Series(data=np.random.randn(100), index=i))
        display.display(plt.gcf())
        display.clear_output(wait=True)
        time.sleep(1)
    except KeyboardInterrupt:
        break


尝试在plot()函数后添加show()gcf().show()。 这些将强制更新当前数字(gcf()返回当前数字的引用)。


将标签添加到此处发布的其他解决方案将继续在每个循环中添加新标签。 要解决这个问题,请使用clf清除绘图

1
2
3
4
5
6
7
8
9
for t in range(100)
   if t % refresh_rate == 0:

     plt.clf()
     plt.plot(history['val_loss'], 'r-', lw=2, label='val')
     plt.plot(history['training_loss'], 'b-', lw=1, label='training')
     plt.legend()
     display.clear_output(wait=True)
     display.display(plt.gcf())