webentwicklung-frage-antwort-db.com.de

So aktualisieren Sie einen Plot in einer Schleife in ipython notebook dynamisch (innerhalb einer Zelle)

Umgebung: Python 2.7, matplotlib 1.3, IPython-Notizbuch 1.1, Linux, Chrome. Der Code befindet sich in einer einzelnen Eingabezelle mit --pylab=inline

Ich möchte IPython-Notizbuch und pandas verwenden, um einen Stream zu konsumieren und alle 5 Sekunden einen Plot dynamisch zu aktualisieren.

Wenn ich nur die print-Anweisung verwende, um die Daten im Textformat zu drucken, funktioniert das einwandfrei: Die Ausgabezelle druckt nur weiter Daten und fügt neue Zeilen hinzu. Aber wenn ich versuche, die Daten zu zeichnen (und sie dann in einer Schleife zu aktualisieren), wird die Zeichnung nie in der Ausgabezelle angezeigt. Aber wenn ich die Schleife entferne, zeichne ich sie einfach einmal. Es funktioniert gut.

Dann habe ich einen einfachen Test gemacht:

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)

Die Ausgabe zeigt nichts an, bis ich den Vorgang manuell unterbreche (Strg + m + i). Und nachdem ich es unterbrochen habe, wird der Plot korrekt als mehrere überlappende Linien angezeigt. Was ich aber wirklich will, ist ein Plot, der alle 5 Sekunden angezeigt und aktualisiert wird (oder wann immer die plot() -Funktion aufgerufen wird, genau wie die oben erwähnten print-Anweisungsausgaben, die gut funktionieren). Nur das endgültige Diagramm zu zeigen, nachdem die Zelle vollständig fertig ist, ist NICHT das, was ich will.

Ich habe sogar versucht, die draw () - Funktion nach jedem plot() usw. explizit hinzuzufügen. Keines von ihnen funktioniert. Fragen Sie sich, wie Sie einen Plot mithilfe einer for/while-Schleife in einer Zelle in IPython Notebook dynamisch aktualisieren können.

73
user3236895

verwenden IPython.display Modul:

%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

Sie können dies weiter verbessern, indem Sie wait=True Zu clear_output Hinzufügen:

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

Ein paar Verbesserungen an HYRYs Antwort :

  • rufe display vor clear_output, so dass Sie am Ende einen Plot haben und nicht zwei, wenn die Zelle unterbrochen wird.
  • fangen Sie das KeyboardInterrupt ab, damit die Zellenausgabe nicht mit dem Traceback verunreinigt wird.
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

Versuchen Sie, show() oder gcf().show() nach der plot() -Funktion einzufügen. Dadurch wird die Aktualisierung der aktuellen Figur erzwungen (gcf () gibt eine Referenz für die aktuelle Figur zurück).

2

Wenn Sie den anderen hier aufgeführten Lösungen Beschriftungen hinzufügen, werden in jeder Schleife neue Beschriftungen hinzugefügt. Um damit umzugehen, löschen Sie den Plot mit 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