How to dynamically update a plot in a loop in IPython notebook (within one cell)
Solution 1
Use the 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)
Solution 2
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
Solution 3
You can further improve this by adding wait=True
to clear_output
:
display.clear_output(wait=True)
display.display(pl.gcf())
Solution 4
I tried many methods, but I found this as the simplest and the easiest way -> to add clear_output(wait=True), for example,
from IPython.display import clear_output
for i in range(n_iterations):
clear_output(wait=True)
x = some value
y = some value
plt.plot(x, y, '-r')
plt.show()
This overwrites on the same plot, and gives an illusion of plot animation
Solution 5
Adding a 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 example:
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())
Related videos on Youtube
user3236895
Updated on October 29, 2021Comments
-
user3236895 over 2 years
Environment: Python 2.7, Matplotlib 1.3, IPython notebook 1.1, Linux, and 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 five seconds.
When I just use a 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 shows up in the output cell. But if I remove the loop, and 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 five 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 the draw() function after each
plot()
, etc. None of them works. How can I dynamically update a plot by a for/while loop within one cell in IPython notebook? -
user3236895 over 10 yearsthanks. gcf().show() also works. Need to add the clear_output() suggested by HYRY to show stuff on the same fig
-
denfromufa over 9 yearsthis is not smooth option, the plot is recreated from scratch with cell going up and down in between
-
ahwillia over 9 years+1. This is very important. I think HYRY's answer should be updated with this info.
-
ahwillia over 9 yearsAdding
clear_output(wait=True)
solves this problem. See wabu's answer below. -
Peter about 9 yearsThis is good, but has the annoying side effect of clearing the print output as well.
-
herrlich10 almost 9 yearsIndeed,
display.display(gcf())
should go BEFOREdisplay.clear_output(wait=True)
-
tacaswell over 8 yearsYou can do better these days with
%matplotlib nbagg
which gives you a live figure to play with. -
Tom Phillips over 8 yearsThanks, @csta. Added it.
-
N. Virgo over 8 years@tcaswell I've added a new question asking how one uses
nbagg
to achieve this. (Pinging you in case you're interested in answering it.) stackoverflow.com/questions/34486642/… -
Jakub Arnold about 6 years@herrlich10 Why should
display
be called beforeclear_output
? Shouldn't you first clear the output and then display the new data, instead of doing it the other way around? -
KIC over 5 yearsthis works but also destroys anything else in the cell like the printed measures. Is there a way really just updating the plot and keeping everything else in place?
-
MasayoMusic over 4 yearsI am still getting a screen flicker with the graph updates, however it's not all the time. Is there a workaround to this?
-
MasayoMusic over 4 yearsIs this in addition to "display.display(pl.gcf())"?
-
MasayoMusic over 4 yearsThanks
plt.clf()
works. However is there anyway to get rid of the flicker from the updates? -
Neil Traft about 3 yearsIf you are also trying to print text at the beginning of the loop, I find that this causes the graph to disappear, so that it is only visible for a split second. I do not have this problem when the
display()
call is placed afterclear_output()
. -
gammapoint about 3 yearsRather than sleeping for 1 second between graph updates, is there a way to make the figure only update after a button press?
-
muammar over 2 yearsWhy is this not working correctly if I use
subplots
?