web-dev-qa-db-fra.com

comment mettre à jour dynamiquement un tracé dans une boucle dans ipython notebook (dans une cellule)

Environnement: Python 2.7, matplotlib 1.3, IPython notebook 1.1, linux, chrome. Le code est dans une seule cellule d'entrée, en utilisant --pylab=inline

Je veux utiliser IPython notebook et pandas pour consommer un flux et mettre à jour de manière dynamique un tracé toutes les 5 secondes.

Lorsque je viens d'utiliser l'instruction print pour imprimer les données au format texte, cela fonctionne parfaitement: la cellule de sortie conserve uniquement l'impression des données et l'ajout de nouvelles lignes. Mais lorsque j'essaie de tracer les données (puis de les mettre à jour en boucle), le tracé n'apparaît jamais dans la cellule de sortie. Mais si je supprime la boucle, tracez-la une seule fois. Ça fonctionne bien.

Ensuite, j'ai fait un test simple:

i = pd.date_range('2013-1-1',periods=100,freq='s')
while True:
    plot(pd.Series(data=np.random.randn(100), index=i))
    #pd.Series(data=np.random.randn(100), index=i).plot() also tried this one
    time.sleep(5)

La sortie ne montrera rien jusqu'à ce que j'interrompe manuellement le processus (ctrl + m + i). Et après l’interrompre, le graphique montre correctement que plusieurs lignes se chevauchent. Mais ce que je veux vraiment, c’est un tracé qui s'affiche et est mis à jour toutes les 5 secondes (ou chaque fois que la fonction plot() est appelée, tout comme l’instruction d’impression que j’ai mentionnée ci-dessus, qui fonctionne bien). Afficher uniquement le graphique final une fois la cellule complétée n’est PAS ce que je veux.

J'ai même essayé d'ajouter explicitement la fonction draw () après chaque plot(), etc. Aucun d'entre eux ne fonctionne. Vous demandez-vous comment mettre à jour de manière dynamique un tracé par une boucle for/while dans une cellule dans le cahier IPython.

73
user3236895

utilisation IPython.display module:

%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
    pl.plot(pl.randn(100))
    display.clear_output(wait=True)
    display.display(pl.gcf())
    time.sleep(1.0)
98
HYRY

Vous pouvez améliorer cela en ajoutant wait=True à clear_output:

display.clear_output(wait=True)
display.display(pl.gcf())
26
wabu

Quelques améliorations sont sur réponse de HYRY :

  • appelez display avant clear_output afin que vous vous retrouviez avec une parcelle plutôt que deux lorsque la cellule est interrompue.
  • récupérez le KeyboardInterrupt, de sorte que la sortie de la cellule ne soit pas encombrée par le suivi.
import matplotlib.pylab as plt
import pandas as pd
import numpy as np
import time
from IPython import display
%matplotlib inline

i = pd.date_range('2013-1-1',periods=100,freq='s')

while True:
    try:
        plt.plot(pd.Series(data=np.random.randn(100), index=i))
        display.display(plt.gcf())
        display.clear_output(wait=True)
        time.sleep(1)
    except KeyboardInterrupt:
        break
25
Tom Phillips

Essayez d'ajouter show() ou gcf().show() après la fonction plot(). Ceux-ci forceront la mise à jour de la figure actuelle (gcf () retourne une référence pour la figure actuelle).

2
Saullo G. P. Castro

Ajouter une étiquette aux autres solutions publiées ici continuera à ajouter de nouvelles étiquettes à chaque boucle. Pour résoudre ce problème, effacez le tracé en utilisant clf

for t in range(100)
   if t % refresh_rate == 0:

     plt.clf()
     plt.plot(history['val_loss'], 'r-', lw=2, label='val')
     plt.plot(history['training_loss'], 'b-', lw=1, label='training')
     plt.legend()
     display.clear_output(wait=True)
     display.display(plt.gcf())

0
muon