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

若如初见. 提交于 2019-12-17 07:01:20

问题


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

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

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.

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.

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.


回答1:


use IPython.display module:

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



回答2:


You can further improve this by adding wait=True to clear_output:

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



回答3:


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

  • call display before clear_output so 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.
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



回答4:


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




回答5:


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

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



来源:https://stackoverflow.com/questions/21360361/how-to-dynamically-update-a-plot-in-a-loop-in-ipython-notebook-within-one-cell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!