Dans les réponses à la mise à jour dynamique d'un tracé dans une boucle dans un bloc-notes ipython (dans une cellule) , un exemple est donné sur la façon de mettre à jour dynamiquement un tracé dans un bloc-notes Jupyter dans une boucle Python. Cependant, cela fonctionne en détruisant et en recréant l'intrigue à chaque itération, et un commentaire dans l'un des fils note que cette situation peut être améliorée en utilisant la %matplotlib nbagg
magie new-ish , qui fournit une figure interactive intégrée dans le cahier, plutôt qu'une image statique.
Cependant, cette merveilleuse nouvelle nbagg
fonctionnalité semble être complètement non documentée pour autant que je sache, et je suis incapable de trouver un exemple de la façon de l'utiliser pour mettre à jour dynamiquement un tracé. Ma question est donc de savoir comment mettre à jour efficacement un tracé existant dans un notebook Jupyter / Python, en utilisant le backend nbagg? Étant donné que la mise à jour dynamique des graphiques dans matplotlib est une question délicate en général, un exemple de travail simple serait d'une grande aide. Un pointeur vers 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 dessiner un tracé de son état actuel, puis de l'exécuter pendant quelques itérations supplémentaires, puis de mettre à jour le tracé pour refléter l'état actuel, et ainsi de suite. L'idée est donc de dessiner un tracé puis, sans aucune interaction de l'utilisateur, de mettre à jour les données du tracé sans détruire et recréer le tout.
Voici un code légèrement modifié de la réponse à la question liée ci-dessus, qui y parvient en redessinant la figure entière à chaque fois. Je veux obtenir 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)
la source
while True:
en une boucle for, quand la boucle se termine, j'obtiens deux images statiques du dernier tracé, plutôt qu'une nbagg interactive. Une idée pourquoi c'est?plt.show()
et en déplaçant la boucle for vers la cellule suivante.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 d'avoir quelques cellules sous le tracé, sinon la vue se met en place chaque fois que le tracé est redessiné.
la source
J'ai adapté la réponse @Ziofil et l'ai modifiée pour accepter x, y comme liste et générer un nuage de points plus une tendance linéaire sur le même graphique.
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();
il vous suffit d'appeler à l'
live_plot(x, y)
intérieur d'une boucle. voici à quoi ça ressemble:la source