Dans les réponses à comment mettre à jour de manière dynamique un tracé dans une boucle dans un bloc-notes ipython (dans une cellule) , un exemple est donné sur la mise à jour dynamique d'un tracé dans un bloc-notes Jupyter dans un Python loop. Cependant, cela fonctionne en détruisant et en recréant le tracé à chaque itération, et un commentaire dans l’un des threads indique que cette situation peut être améliorée en utilisant new-ish %matplotlib nbagg
magic, qui fournit une figure interactive intégrée dans le cahier plutôt qu'une image statique.
Cependant, cette nouvelle fonctionnalité merveilleuse nbagg
semble totalement non documentée, et je suis incapable de trouver un exemple d'utilisation de celle-ci pour mettre à jour dynamiquement un tracé. Voici donc ma question comment mettre à jour efficacement un tracé existant dans un cahier Jupyter/Python, en utilisant le backend nbagg? La mise à jour dynamique des tracés dans matplotlib est un problème épineux en général, un simple exemple pratique serait une aide considérable. Un pointeur sur toute documentation sur le sujet serait également extrêmement utile.
Pour être clair, ce que je demande: ce que je veux faire est d’exécuter du code de simulation pour quelques itérations, puis de tracer un tracé de son état actuel, de l’exécuter pendant quelques itérations supplémentaires, puis de mettre à jour le tracé pour qu’il reflète l'état actuel, etc. L'idée est donc de dessiner un graphique et ensuite, sans aucune interaction de l'utilisateur, de mettre à jour les données dans le graphique sans détruire ni recréer le tout.
Voici un code légèrement modifié à partir de la réponse à la question liée ci-dessus, qui y parvient en reprenant chaque fois la figure entière. Je veux atteindre le même résultat, mais plus efficacement en utilisant 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)
Voici un exemple qui met à jour un tracé dans une boucle. Il met à jour les données de la figure et ne redessine pas la figure entière à chaque fois. Il bloque l'exécution, mais si vous souhaitez exécuter un ensemble fini de simulations et enregistrer les résultats quelque part, cela ne vous pose pas de problème.
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import time
def pltsin(ax, colors=['b']):
x = np.linspace(0,1,100)
if ax.lines:
for line in ax.lines:
line.set_xdata(x)
y = np.random.random(size=(100,1))
line.set_ydata(y)
else:
for color in colors:
y = np.random.random(size=(100,1))
ax.plot(x, y, color)
fig.canvas.draw()
fig,ax = plt.subplots(1,1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
for f in range(5):
pltsin(ax, ['b', 'r'])
time.sleep(1)
J'affiche ceci sur nbviewer ici.
Il existe une version du widget IPython de nbagg
actuellement en cours de traitement dans le référentiel Matplotlib . Quand cela sera disponible, ce sera probablement le meilleur moyen d’utiliser nbagg
.
EDIT: mis à jour pour afficher plusieurs parcelles
J'utilise jupyter-lab et cela fonctionne pour moi (adaptez-le à votre cas):
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();
Ensuite, dans une boucle, vous remplissez un dictionnaire et vous le transmettez à 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)
assurez-vous de disposer de quelques cellules sous le graphique, sinon la vue s'emboîte chaque fois que le graphique est redessiné.