Cómo actualizar un gráfico en matplotlib

Resuelto thenickname asked hace 13 años • 8 respuestas

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)
thenickname avatar Nov 04 '10 22:11 thenickname
Aceptado

Básicamente tienes dos opciones:

  1. Haga exactamente lo que está haciendo actualmente, pero llame graph1.clear()y graph2.clear()antes de volver a registrar los datos. Esta es la opción más lenta, pero más simple y robusta.

  2. 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()
Joe Kington avatar Nov 04 '2010 16:11 Joe Kington

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()
Arindam avatar Mar 21 '2018 18:03 Arindam

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()
Julian avatar Dec 12 '2019 04:12 Julian

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.

Victor Basso avatar Jan 24 '2015 17:01 Victor Basso