En las respuestas sobre cómo actualizar dinámicamente una gráfica en un bucle en el cuaderno ipython (dentro de una celda) , se da un ejemplo de cómo actualizar dinámicamente una gráfica dentro de un cuaderno Jupyter dentro de un bucle Python. Sin embargo, esto funciona destruyendo y recreando la trama en cada iteración, y un comentario en uno de los hilos señala que esta situación se puede mejorar usando la %matplotlib nbagg
magia nueva , que proporciona una figura interactiva incrustada en el cuaderno, en lugar de que una imagen estática.
Sin embargo, esta maravillosa nbagg
característica nueva parece estar completamente indocumentada por lo que puedo decir, y no puedo encontrar un ejemplo de cómo usarla para actualizar dinámicamente una trama. Por lo tanto, mi pregunta es, ¿cómo se actualiza de manera eficiente una trama existente en un cuaderno Jupyter / Python, usando el backend nbagg? Dado que la actualización dinámica de gráficos en matplotlib es un problema complicado en general, un ejemplo de trabajo simple sería de gran ayuda. Un puntero a cualquier documentación sobre el tema también sería de gran ayuda.
Para que quede claro lo que estoy pidiendo: lo que quiero hacer es ejecutar un código de simulación para algunas iteraciones, luego dibujar un diagrama de su estado actual, luego ejecutarlo para algunas iteraciones más, luego actualizar el diagrama para reflejar el estado actual y así sucesivamente. Entonces, la idea es dibujar una trama y luego, sin ninguna interacción por parte del usuario, actualizar los datos en la trama sin destruir y volver a crear todo.
Aquí hay un código ligeramente modificado de la respuesta a la pregunta vinculada anterior, que logra esto al volver a dibujar la figura completa cada vez. Quiero lograr el mismo resultado, pero usando de manera más eficiente nbagg
.
%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
pl.clf()
pl.plot(pl.randn(100))
display.display(pl.gcf())
display.clear_output(wait=True)
time.sleep(1.0)
fuente
while True:
a un bucle for, cuando el bucle finaliza, obtengo dos imágenes estáticas del último gráfico, en lugar de una nbagg interactiva. ¿Alguna idea de por qué es eso?plt.show()
y mover el bucle for a la siguiente celda.Estoy usando jupyter-lab y esto funciona para mí (adáptelo a su caso):
from IPython.display import clear_output from matplotlib import pyplot as plt import collections %matplotlib inline def live_plot(data_dict, figsize=(7,5), title=''): clear_output(wait=True) plt.figure(figsize=figsize) for label,data in data_dict.items(): plt.plot(data, label=label) plt.title(title) plt.grid(True) plt.xlabel('epoch') plt.legend(loc='center left') # the plot evolves to the right plt.show();
Luego, en un bucle, llena un diccionario y lo pasa a
live_plot()
:data = collections.defaultdict(list) for i in range(100): data['foo'].append(np.random.random()) data['bar'].append(np.random.random()) data['baz'].append(np.random.random()) live_plot(data)
asegúrese de tener algunas celdas debajo del gráfico; de lo contrario, la vista se ajusta en su lugar cada vez que se vuelve a dibujar el gráfico.
fuente
He adaptado la respuesta de @Ziofil y la modifiqué para aceptar x, y como lista y generar un diagrama de dispersión más una tendencia lineal en el mismo diagrama.
from IPython.display import clear_output from matplotlib import pyplot as plt %matplotlib inline def live_plot(x, y, figsize=(7,5), title=''): clear_output(wait=True) plt.figure(figsize=figsize) plt.xlim(0, training_steps) plt.ylim(0, 100) x= [float(i) for i in x] y= [float(i) for i in y] if len(x) > 1: plt.scatter(x,y, label='axis y', color='k') m, b = np.polyfit(x, y, 1) plt.plot(x, [x * m for x in x] + b) plt.title(title) plt.grid(True) plt.xlabel('axis x') plt.ylabel('axis y') plt.show();
solo necesitas llamar
live_plot(x, y)
dentro de un bucle. así es como se ve:fuente