如何在matplotlib中更新图?

the*_*ame 133 python tkinter matplotlib

我在这里重新绘制数字时遇到问题.我允许用户在时间刻度(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)
Run Code Online (Sandbox Code Playgroud)

Joe*_*ton 153

你基本上有两个选择:

  1. 究竟你现在正在做什么,但拨打graph1.clear()graph2.clear()型重构数据之前.这是最慢,但最简单,最强大的选择.

  2. 您可以只更新绘图对象的数据,而不是重新绘制.您需要对代码进行一些更改,但这应该比每次重新绘制事物快得多.但是,您绘制的数据的形状无法更改,如果数据范围发生变化,则需要手动重置x和y轴限制.

举一个第二个选项的例子:

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()
Run Code Online (Sandbox Code Playgroud)

  • 你需要在draw方法之后添加:fig.canvas.flush_events() (16认同)
  • 这是2k14,我偶然发现了这样的事情...它按预期工作但绘图窗口正在变"没有响应"..任何建议? (3认同)

Ari*_*dam 25

您还可以执行以下操作:这将在绘图上绘制10x1随机矩阵数据,用于for循环的50个循环.

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()
Run Code Online (Sandbox Code Playgroud)

  • 哈哈,当我删除`plt.clf()`时为我工作。哦`matplotlib`,你这个流氓:) (3认同)
  • 但这不是更新一个情节!它绘制了 50 个图! (3认同)

Vit*_*uel 14

这对我有用.每次重复调用更新图形的函数.

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()
Run Code Online (Sandbox Code Playgroud)

"fun"是一个返回整数的函数.FuncAnimation会反复调用"update",它会做"xmax"次.

  • 请注意,“a =”是必需的,否则 FuncAnimation 将被垃圾收集并且代码将无法工作! (2认同)

小智 8

如果有人遇到这篇文章寻找我正在寻找的东西,我发现了一些例子

如何使用Matplotlib可视化标量2D数据?

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

然后修改它们以使用imshow与输入堆栈的帧,而不是动态生成和使用轮廓.


从形状(nBins,nBins,nBins)的3D图像阵列开始,称为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)
Run Code Online (Sandbox Code Playgroud)

我还发现了一个更简单的方法来完成整个过程,尽管不太健壮:

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
Run Code Online (Sandbox Code Playgroud)

请注意,这两者似乎只能使用ipython --pylab=tk,也就是说backend = TkAgg

感谢您对一切的帮助.


Jul*_*ian 6

这对我有用:

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()
Run Code Online (Sandbox Code Playgroud)

  • 它仅适用于 Jupyter 笔记本 (5认同)

Sco*_*ott 5

我发布了一个名为python-drawnow的软件包,它提供了一个更新的功能,通常在for循环中调用,类似于Matlab 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)
Run Code Online (Sandbox Code Playgroud)

此包适用于任何matplotlib图,并提供在每次图更新或放入调试器后等待的选项.

  • 它如何同时健壮和不稳定? (3认同)
  • 我的意思是在“适用于任何 matplotlib 图形”中是稳健的,而在“周末项目”中是不稳定的。我已经更新了我的答案 (3认同)