问题
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
beforeclear_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