如何在 ipython notebook 循环中动态更新绘图(在一个单元格内)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21360361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 22:41:13  来源:igfitidea点击:

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

pythonmatplotlibpandasipythonipython-notebook

提问by user3236895

Environment: Python 2.7, matplotlib 1.3, IPython notebook 1.1, linux, chrome. The code is in one single input cell, using --pylab=inline

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

I want to use IPython notebook and pandas to consume a stream and dynamically update a plot every 5 seconds.

我想使用 IPython notebook 和 pandas 来消耗一个流并每 5 秒动态更新一个图。

When I just use print statement to print the data in text format, it works perfectly fine: the output cell just keeps printing data and adding new rows. But when I try to plot the data (and then update it in a loop), the plot never show up in the output cell. But if I remove the loop, just plot it once. It works fine.

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

Then I did some simple test:

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

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)

The output will not show anything until I manually interrupt the process (ctrl+m+i). And after I interrupt it, the plot shows correctly as multiple overlapped lines. But what I really want is a plot that shows up and gets updated every 5 seconds (or whenever the plot()function gets called, just like what print statement outputs I mentioned above, which works well). Only showing the final chart after the cell is completely done is NOT what i want.

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

I even tried to explicitly add draw() function after each plot(), etc. None of them works. Wonder how to dynamically update a plot by a for/while loop within one cell in IPython notebook.

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

采纳答案by HYRY

use IPython.displaymodule:

使用IPython.display模块:

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

回答by Saullo G. P. Castro

Try to add show()or gcf().show()after the plot()function. These will force the current figure to update (gcf() returns a reference for the current figure).

尝试在功能后添加show()或。这些将强制更新当前图形(gcf() 返回当前图形的引用)。gcf().show()plot()

回答by wabu

You can further improve this by adding wait=Trueto clear_output:

您可以通过添加wait=Trueclear_output以下内容来进一步改进:

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

回答by Tom Phillips

A couple of improvement's on HYRY's answer:

HYRY 的回答进行了一些改进:

  • call displaybefore clear_outputso that you end up with one plot, rather than two, when the cell is interrupted.
  • catch the KeyboardInterrupt, so that the cell output isn't littered with the traceback.
  • 调用displaybeforeclear_output以便在单元格中断时最终得到一个图,而不是两个图。
  • 捕获KeyboardInterrupt,以便单元格输出不会与回溯散落。
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

回答by muon

Adding label to the other solutions posted here will keep adding new labels in every loop. To deal with that, clear the plot using clf

向此处发布的其他解决方案添加标签将在每个循环中不断添加新标签。要解决这个问题,请使用clf

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