Ipythonノートブック(1つのセル内)でループ内のプロットを動的に更新する方法


92

環境:Python 2.7、matplotlib 1.3、IPython notebook 1.1、linux、chrome。コードは、1つの単一の入力セルにあります。--pylab=inline

IPythonノートブックとパンダを使用してストリームを消費し、5秒ごとに動的にプロットを更新したいと思います。

printステートメントを使用してデータをテキスト形式で印刷すると、完全に正常に機能します。出力セルはデータを印刷し続け、新しい行を追加します。しかし、データをプロットしようとすると(その後ループで更新しようとすると)、出力セルにプロットが表示されません。ただし、ループを削除した場合は、1回だけプロットします。正常に動作します。

次に、簡単なテストをいくつか行いました。

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()関数が呼び出されたときはいつでも、上で述べた印刷ステートメントの出力と同様に、うまく機能します)。セルが完全に完了した後に最終的なチャートを表示するだけでは、私は望みません。

それぞれの後にdraw()関数を明示的に追加することなども試みましたplot()。どれも機能しません。IPython Notebookの1つのセル内でfor / whileループによってプロットを動的に更新する方法を知りましょう。

回答:


118

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)

4
これはスムーズなオプションではありません。プロットは最初から再作成され、その間にセルが上下に移動します
denfromufa

3
追加clear_output(wait=True)するとこの問題は解決します。以下のwabuの回答を参照してください。
アレックスウィリアムズ

3
あなたは、あなたが%matplotlib nbagg遊んでいる生きている姿をあなたに与える今日でよりよくすることができます。
tacaswell 2015

@tcaswell私はnbaggこれを達成するためにどのように使用するかを尋ねる新しい質問を追加しました。(あなたがそれに答えることに興味を持っている場合には、あなたのping。)stackoverflow.com/questions/34486642/...
ナサニエル

3
これは機能しますが、印刷された小節のようなセル内の他のものも破壊します。実際にプロットを更新し、他のすべてを適切に維持する方法はありますか?
KIC 2018

30

これをさらに改善するには、以下を追加wait=Trueclear_outputます。

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

1
+1。これは非常に重要です。HYRYの答えはこの情報で更新されるべきだと思います。
Alex Williams

5
これは良いことですが、印刷出力をクリアするという面倒な副作用もあります。
ピーター

30

HYRYの回答をいくつか改善しました

  • display前に電話するclear_outputセルが中断されたときに、2つではなく1つのプロットなるます。
  • をキャッチし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

7
確かに、前にdisplay.display(gcf())行く必要があります display.clear_output(wait=True)
herrlich10 2015

ありがとう、@ csta。追加しました。
トムフィリップス

@ herrlich10なぜdisplay前に呼び出す必要があるのclear_outputですか?逆に行う代わりに、最初に出力をクリアしてから新しいデータを表示するべきではありませんか?
ヤクブアーノルド

1
グラフが更新されても画面がちらつきますが、常にそうとは限りません。これに対する回避策はありますか?
MasayoMusic

2

追加しようとしshow()たりgcf().show()した後にplot()機能。これらは現在の図を強制的に更新します(gcf()は現在の図の参照を返します)。


2
ありがとう。gcf()。show()も機能します。同じイチジクに物事を表示するには、HYRYに​​よって提案されたclear_output()を追加する必要があります
user3236895

これは「display.display(pl.gcf())」に追加されますか?
MasayoMusic

2

ここに投稿された他のソリューションにラベルを追加すると、すべてのループで新しいラベルが追加され続けます。これに対処するには、以下を使用してプロットをクリアします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())

4
ありがとうplt.clf()。しかし、とにかく更新からちらつきを取り除く方法はありますか?
MasayoMusic

0

このようにできます。リストとしてx、yを受け入れ、散布図と同じプロットの線形トレンドを出力します。

from IPython.display import clear_output
from matplotlib import pyplot as plt
%matplotlib inline
    
def live_plot(x, y, figsize=(7,5), title=''):
    clear_output(wait=True)
    plt.figure(figsize=figsize)
    plt.xlim(0, training_steps)
    plt.ylim(0, 100)
    x= [float(i) for i in x]
    y= [float(i) for i in y]
    
    if len(x) > 1:
        plt.scatter(x,y, label='axis y', color='k') 
        m, b = np.polyfit(x, y, 1)
        plt.plot(x, [x * m for x in x] + b)

    plt.title(title)
    plt.grid(True)
    plt.xlabel('axis x')
    plt.ylabel('axis y')
    plt.show();

live_plot(x, y)ループ内で呼び出す必要があるだけです。以下にその外観を示します。 ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.