W odpowiedziach na to, jak dynamicznie aktualizować wykres w pętli w notatniku ipython (w obrębie jednej komórki) , podano przykład dynamicznego aktualizowania wykresu w notatniku Jupyter w pętli Pythona. Działa to jednak poprzez niszczenie i ponowne tworzenie fabuły w każdej iteracji, a komentarz w jednym z wątków zauważa, że tę sytuację można poprawić za pomocą nowej %matplotlib nbagg
magii, która zapewnia raczej interaktywną figurę osadzoną w notatniku, niż statyczny obraz.
Jednak ta wspaniała nowa nbagg
funkcja wydaje się być całkowicie nieudokumentowana, o ile wiem, i nie mogę znaleźć przykładu, jak jej użyć do dynamicznej aktualizacji fabuły. Dlatego moje pytanie brzmi, jak skutecznie zaktualizować istniejącą działkę w notatniku Jupyter / Python, używając zaplecza nbagg? Ponieważ dynamiczne aktualizowanie wykresów w matplotlib jest ogólnie trudnym problemem, prosty przykład roboczy byłby ogromną pomocą. Niezwykle pomocny byłby również wskaźnik do dowolnej dokumentacji na ten temat.
Aby było jasne, o co proszę: chcę uruchomić kod symulacji na kilka iteracji, następnie narysować wykres jego obecnego stanu, a następnie uruchomić go przez kilka kolejnych iteracji, a następnie zaktualizować wykres, aby odzwierciedlić aktualny stan i tak dalej. Chodzi więc o to, aby narysować fabułę, a następnie, bez żadnej interakcji ze strony użytkownika, zaktualizować dane na wykresie bez niszczenia i ponownego tworzenia całości.
Oto nieco zmodyfikowany kod z odpowiedzi na powyższe pytanie, do którego prowadzi łącze, w którym za każdym razem rysuje się od nowa całą figurę. Chcę osiągnąć ten sam efekt, ale wydajniej używając 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)
źródło
while True:
pętlę na for, kiedy pętla się kończy, otrzymuję dwa statyczne obrazy ostatniej działki, zamiast interaktywnego nbagg. Masz jakiś pomysł, dlaczego tak jest?plt.show()
i przenoszenia pętli for do następnej komórki.Używam jupyter-lab i to działa dla mnie (dostosuj to do swojego przypadku):
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();
Następnie w pętli wypełniasz słownik i przekazujesz go do
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)
upewnij się, że masz kilka komórek pod wykresem, w przeciwnym razie widok zostanie zatrzymany za każdym razem, gdy wykres jest przerysowywany.
źródło
Zaadaptowałem odpowiedź @Ziofil i zmodyfikowałem ją tak, aby akceptowała x, y jako listę i wyświetlała wykres punktowy oraz trend liniowy na tym samym wykresie.
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();
wystarczy zadzwonić
live_plot(x, y)
w pętli. tak to wygląda:źródło