Jupyter / iPythonでプロットを動的に更新する現在の正しい方法は何ですか?


93

ipythonノートブック(1つのセル内)のループ内のプロットを動的に更新する方法の回答では、Pythonループ内のJupyterノートブック内のプロットを動的に更新する方法の例が示されています。ただし、これは反復ごとにプロットを破棄して再作成することで機能し、スレッドの1つにあるコメントで%matplotlib nbaggは、ノートブックに埋め込まれたインタラクティブな図を提供する新しい魔法を使用することで、この状況を改善できると述べています。静止画像よりも。

しかし、この素晴らしい新nbagg機能は、私が知る限り完全に文書化されていないようであり、それを使用してプロットを動的に更新する方法の例を見つけることができません。したがって、私の質問は、nbaggバックエンドを使用して、Jupyter / Pythonノートブックの既存のプロットをどのように効率的に更新するのかということです。matplotlibでプロットを動的に更新することは一般に難しい問題であるため、簡単な実例は非常に役立ちます。このトピックに関するドキュメントへのポインタも非常に役立ちます。

私が求めていることを明確にするために:私がしたいのは、シミュレーションコードを数回実行し、現在の状態のプロットを描画し、さらに数回実行し、プロットを更新して反映することです現在の状態など。したがって、アイデアは、プロットを描画し、ユーザーの操作なしで、全体を破壊して再作成することなく、プロット内のデータを更新することです。

上記のリンクされた質問への回答から少し変更されたコードがあります。これは、毎回図全体を再描画することでこれを実現します。同じ結果を達成したいのですが、を使用するとより効率的になりnbaggます。

%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
    pl.clf()
    pl.plot(pl.randn(100))
    display.display(pl.gcf())
    display.clear_output(wait=True)
    time.sleep(1.0)

回答:


62

これは、ループ内のプロットを更新する例です。図のデータを更新し、図全体を毎回再描画するわけではありません。実行をブロックしますが、有限のシミュレーションセットを実行して結果をどこかに保存することに関心がある場合は、問題にならない可能性があります。

%matplotlib notebook

import numpy as np
import matplotlib.pyplot as plt
import time

def pltsin(ax, colors=['b']):
    x = np.linspace(0,1,100)
    if ax.lines:
        for line in ax.lines:
            line.set_xdata(x)
            y = np.random.random(size=(100,1))
            line.set_ydata(y)
    else:
        for color in colors:
            y = np.random.random(size=(100,1))
            ax.plot(x, y, color)
    fig.canvas.draw()

fig,ax = plt.subplots(1,1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
for f in range(5):
    pltsin(ax, ['b', 'r'])
    time.sleep(1)

私はこれをここのnbviewerに載せました。

現在Matplotlibリポジトリで作業中のIPythonWidgetバージョンnbaggがあります。それが利用可能である場合、それはおそらく使用するための最良の方法でしょうnbagg

編集:複数のプロットを表示するように更新


1
素晴らしい、それはうまく機能しているようです。実行中の対話性の欠如は、私にとって大きな問題ではありません。少し奇妙なことwhile True:に、をforループに変更すると、ループが終了すると、インタラクティブなnbaggではなく、最後のプロットの2つの静止画像が取得されます。それがなぜであるかについて何か考えはありますか?
ナサニエル

whileをforループに変更し、tmpnb.orgで試しましたが、2番目の画像が表示されないか、対話性が失われています。暗闇の中で撮影しますが、関数内にループを含めるのではなく、関数の呼び出しの周りでループを移動してみることができます。range(10)のfの場合:pltsin(ax)time.sleep(1)
空気圧

3
@pneumatics残念ながら、RetinaディスプレイのMatplotlib2.0にはいくつかの問題があります。ループ内のプロットは通常の2倍小さくなっています。
アレクサンダーロディン

1
フィギュアは自分自身を正しくサイズ変更する時間が与えられていないようです。そのplt.show()ため、forループを次のセルに配置して移動すると、はるかに優れたエクスペリエンスが得られました。
ImportanceOfBeingErnest

2
プロットと同じjupyterノートブックセルに%matplotlibノートブックがあることを確認してください-インポート
ステートメントの

12

私はjupyter-labを使用していますが、これは私にとってはうまくいきます(あなたのケースに適応させてください):

from IPython.display import clear_output
from matplotlib import pyplot as plt
import collections
%matplotlib inline

def live_plot(data_dict, figsize=(7,5), title=''):
    clear_output(wait=True)
    plt.figure(figsize=figsize)
    for label,data in data_dict.items():
        plt.plot(data, label=label)
    plt.title(title)
    plt.grid(True)
    plt.xlabel('epoch')
    plt.legend(loc='center left') # the plot evolves to the right
    plt.show();

次に、ループで辞書にデータを入力し、それをlive_plot()次の宛先に渡します。

data = collections.defaultdict(list)
for i in range(100):
    data['foo'].append(np.random.random())
    data['bar'].append(np.random.random())
    data['baz'].append(np.random.random())
    live_plot(data)

プロットの下にいくつかのセルがあることを確認してください。そうしないと、プロットが再描画されるたびにビューが所定の位置にスナップします。


1
これにより、既存のプロットを更新するのではなく、毎回新しいプロットが作成されます
空気圧

2
正しい。jupyter-labで動的プロットを作成するためのより良い方法は見つかりませんでした。
Ziofil

1
反復間の待機時間を設定する方法はありますか?単に「待機=真」にするのではなく
AhmadMoussa19年

1
プロットが再描画されるたびに、グラフがちらつきます。この問題を解決する方法はありますか?プロットの下にいくつかの空のセルがありますが、それは役に立たないようです。
MasayoMusic

「ちらつきやジャンプの出力」を参照してください@MasayoMusic buildmedia.readthedocs.org/media/pdf/ipywidgets/latest/...
レオ

0

@Ziofil回答を適応させ、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.