如何在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)
539138 次浏览

你基本上有两个选择:

  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()

以上可能都是正确的,但是对我来说,“在线更新”数字只适用于某些后端,特别是wx。你可以尝试更改为这个,例如通过ipython --pylab=wx开始ipython/pylab !好运!

我已经发布了一个名为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)

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

这对我很管用。重复调用一个函数,每次更新图形。

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”次

你还可以这样做: 这将在图上绘制一个10x1随机矩阵数据,循环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()

这招对我很管用:

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()

根据其他答案,我将图形的更新包装在python装饰器中,以将图形的更新机制与实际的图形分开。这样,就更容易更新任何情节。

def plotlive(func):
plt.ion()


@functools.wraps(func)
def new_func(*args, **kwargs):


# Clear all axes in the current figure.
axes = plt.gcf().get_axes()
for axis in axes:
axis.cla()


# Call func to plot something
result = func(*args, **kwargs)


# Draw the plot
plt.draw()
plt.pause(0.01)


return result


return new_func

使用的例子

然后你可以像使用其他装饰器一样使用它。

@plotlive
def plot_something_live(ax, x, y):
ax.plot(x, y)
ax.set_ylim([0, 100])

唯一的限制是你必须在循环之前创建图形:

fig, ax = plt.subplots()
for i in range(100):
x = np.arange(100)
y = np.full([100], fill_value=i)
plot_something_live(ax, x, y)