matplotlibのプロットを更新する方法は?


156

ここで図を再描画することに問題があります。ユーザーが時間スケール(x軸)で単位を指定できるようにしてから、この関数を再計算して呼び出しますplots()。プロットを単純に更新し、図に別のプロットを追加しないでください。

def plots():
    global vlgaBuffSorted
    cntr()

    result = collections.defaultdict(list)
    for d in vlgaBuffSorted:
        result[d['event']].append(d)

    result_list = result.values()

    f = Figure()
    graph1 = f.add_subplot(211)
    graph2 = f.add_subplot(212,sharex=graph1)

    for item in result_list:
        tL = []
        vgsL = []
        vdsL = []
        isubL = []
        for dict in item:
            tL.append(dict['time'])
            vgsL.append(dict['vgs'])
            vdsL.append(dict['vds'])
            isubL.append(dict['isub'])
        graph1.plot(tL,vdsL,'bo',label='a')
        graph1.plot(tL,vgsL,'rp',label='b')
        graph2.plot(tL,isubL,'b-',label='c')

    plotCanvas = FigureCanvasTkAgg(f, pltFrame)
    toolbar = NavigationToolbar2TkAgg(plotCanvas, pltFrame)
    toolbar.pack(side=BOTTOM)
    plotCanvas.get_tk_widget().pack(side=TOP)

回答:


178

基本的に2つのオプションがあります。

  1. あなたが現在やっていることを正確に行いますが、呼び出すgraph1.clear()graph2.clear()、データを再プロットする前に。これは最も低速ですが、最も単純で最も堅牢なオプションです。

  2. 再プロットする代わりに、プロットオブジェクトのデータを更新できます。コードに変更を加える必要がありますが、これは毎回再プロットするよりもはるかに高速です。ただし、プロットするデータの形状は変更できません。また、データの範囲が変化する場合は、x軸とy軸の範囲を手動でリセットする必要があります。

2番目のオプションの例を示すには:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 6*np.pi, 100)
y = np.sin(x)

# You probably won't need this if you're embedding things in a tkinter plot...
plt.ion()

fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma

for phase in np.linspace(0, 10*np.pi, 500):
    line1.set_ydata(np.sin(x + phase))
    fig.canvas.draw()
    fig.canvas.flush_events()

「1」を試してみました。その結果、データを再プロットした後、別の一連のプロットがGUIに描画されたため、再計算後、以前と同様に4つのプロットができました。
ニックネーム11/10/4

@thenickname-あなたのコードのどこを呼び出していclearますか?あなたは呼び出すべきであるgraph1.clear(); graph2.clear()あなたの内側forを呼び出す直前に、ループgraph1.plot(...)graph2.plot(...)等...
ジョー・キングトン

そのforループは、calles graphx.plot(...)をN回作成し、そこにclearステートメントを入れると、最後のものだけがプロットされます。私は実際にキャンバスコードを引き出して、Figureコードと一緒にメインプログラムループに入れました。これで、ボタンから関数が呼び出されます。何らかの理由で、関数を呼び出しただけでプロットが更新されますが、ボタンを押してもプロットは更新されません。それはかなり興味深い振る舞いです。Tkinterのバグだと思います。
ニックネーム

ただの予感...あなたは電話を逃しfig.canvas.draw()たりplt.draw()、各フレームをプロットした後ですか?(Ieはあなたがのシーケンスを持つ必要がありclearplotdrawあなたはフレームを表示するたびに)私は推測しているが、私はそれはあなたが記述している...幸運を、任意の割合で正確に行動を起こすだろうと思います!
Joe Kington、2010年

3
それは2k14であり、私はこのような何かを達成するためにつまずきました...それは期待どおりに機能しますが、プロットウィンドウは「応答していません」になっています。
DevC 2014

39

次のようにすることもできます。これにより、forループの50サイクルのプロットに10x1のランダムマトリックスデータが描画されます。

import matplotlib.pyplot as plt
import numpy as np

plt.ion()
for i in range(50):
    y = np.random.random([10,1])
    plt.plot(y)
    plt.draw()
    plt.pause(0.0001)
    plt.clf()

これはグラフを出力していないようです。何か不足していますか?私が持っている%matplotlib inlineだけでなくJupyterノートに。
MasayoMusic

ハハ、私がを取り外したときに私のために働いたplt.clf()。ああmatplotlib、あなたはラスカル:)
AndyP

15

これでうまくいきました。毎回グラフを更新する関数を繰り返し呼び出します。

import matplotlib.pyplot as plt
import matplotlib.animation as anim

def plot_cont(fun, xmax):
    y = []
    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)

    def update(i):
        yi = fun()
        y.append(yi)
        x = range(len(y))
        ax.clear()
        ax.plot(x, y)
        print i, ': ', yi

    a = anim.FuncAnimation(fig, update, frames=xmax, repeat=False)
    plt.show()

「fun」は整数を返す関数です。FuncAnimationは "update"を繰り返し呼び出し、 "xmax"回実行します。


この関数の呼び出し方法(特に、関数呼び出しで関数を渡す方法)の例と、fun()関数の例を教えてください。
bjornasm 2015年

1
承知しました。「fun()」は整数を返す関数です。「plot_cont(my_function、123)」のように、関数を引数として関数に渡すことができます。そこには、私はライン86でplot_contを呼び出していますgithub.com/vitobasso/audio-ml/blob/...
Vituel

1
「a =」が必要であるか、またはFuncAnimationがガベージコレクションされ、コードが機能しないことに注意してください。
Kiuhnm 2018

8

私が探していたものを探している誰かがこの記事に出くわした場合、私は例を見つけました

Matplotlibでスカラー2Dデータを視覚化する方法は?

そして

http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop(web.archive.org)

次に、輪郭を即座に生成して使用する代わりに、フレームの入力スタックでimshowを使用するようにそれらを変更しました。


と呼ばれる形状の画像の3D配列(nBins、nBins、nBins)から始めframesます。

def animate_frames(frames):
    nBins   = frames.shape[0]
    frame   = frames[0]
    tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
    for k in range(nBins):
        frame   = frames[k]
        tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
        del tempCS1
        fig.canvas.draw()
        #time.sleep(1e-2) #unnecessary, but useful
        fig.clf()

fig = plt.figure()
ax  = fig.add_subplot(111)

win = fig.canvas.manager.window
fig.canvas.manager.window.after(100, animate_frames, frames)

また、堅牢性は低くなりますが、このプロセス全体を簡単に実行できる方法も見つけました。

fig = plt.figure()

for k in range(nBins):
    plt.clf()
    plt.imshow(frames[k],cmap=plt.cm.gray)
    fig.canvas.draw()
    time.sleep(1e-6) #unnecessary, but useful

これらの両方がだけで動作するように見えることに注意ipython --pylab=tk別名、backend = TkAgg

すべてで助けてくれてありがとう。


6

Matlabと同様に、通常forループ内で呼び出される、Figureを更新する機能を提供するpython-drawnowというパッケージをリリースしましたdrawnow

使用例:

from pylab import figure, plot, ion, linspace, arange, sin, pi
def draw_fig():
    # can be arbitrarily complex; just to draw a figure
    #figure() # don't call!
    plot(t, x)
    #show() # don't call!

N = 1e3
figure() # call here instead!
ion()    # enable interactivity
t = linspace(0, 2*pi, num=N)
for i in arange(100):
    x = sin(2 * pi * i**2 * t / 100.0)
    drawnow(draw_fig)

このパッケージは、任意のmatplotlib Figureで動作し、各Figureの更新後に待機するか、デバッガーにドロップするオプションを提供します。


2
同時に堅牢で不安定なのはなぜですか?
BlueMoon93 2016年

2
「matplotlibの図で動作する」のように堅牢で、「週末のプロジェクト」のように不安定であることを意味しました。回答を更新しました
Scott

3

上記のすべてが当てはまる可能性がありますが、私にとって、数値の「オンライン更新」は一部のバックエンドでのみ機能しwxます。あなたはこれに変更しようとするかもしれません、例えばipython --pylab=wx!によってipython / pylabを開始することによって!幸運を!


1
メッセージありがとうございます。インタラクティブモードは、使用したデフォルトのバックエンドでは機能しなかったため、使用しませんでした。グラフを表示するたびに実行を停止するよりも、インタラクティブモードを使用するほうがはるかに便利です。
PierreE 2013

1
他の回答はどれも私の場合には役に立ちませんでした。私はpycharmを使用していますが、問題はコンソールのプロットと対話性にありました。インタラクティブをオンにするには、コード本体にFrom pylab import *を追加してから、ion()を追加する必要がありました。今では問題なく動作しています。
shelbypereira 2017年

2

これは私のために働きました:

from matplotlib import pyplot as plt
from IPython.display import clear_output
import numpy as np
for i in range(50):
    clear_output(wait=True)
    y = np.random.random([10,1])
    plt.plot(y)
    plt.show()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.