Cómo actualizar un gráfico en matplotlib
Tengo problemas para volver a dibujar la figura aquí. Permito que el usuario especifique las unidades en la escala de tiempo (eje x) y luego recalculo y llamo a esta función plots()
. Quiero que el gráfico simplemente se actualice, no que se agregue otro gráfico a la figura.
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)
Básicamente tienes dos opciones:
Haga exactamente lo que está haciendo actualmente, pero llame
graph1.clear()
ygraph2.clear()
antes de volver a registrar los datos. Esta es la opción más lenta, pero más simple y robusta.En lugar de volver a trazar, puede simplemente actualizar los datos de los objetos del trazado. Necesitará realizar algunos cambios en su código, pero esto debería ser mucho, mucho más rápido que volver a trazar las cosas cada vez. Sin embargo, la forma de los datos que está trazando no puede cambiar y, si el rango de sus datos cambia, deberá restablecer manualmente los límites de los ejes x e y.
Para dar un ejemplo de la segunda opción:
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()
También puede hacer lo siguiente: Esto dibujará una matriz aleatoria de 10x1 en el gráfico durante 50 ciclos del bucle for.
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()
Esto funcionó para mí:
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()
Esto funcionó para mí. Llama repetidamente a una función que actualiza el gráfico cada vez.
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()
"divertido" es una función que devuelve un número entero. FuncAnimation llamará repetidamente a "actualizar", lo hará "xmax" veces.