Ipython not defterinde (bir hücre içinde) döngüdeki bir grafiği dinamik olarak güncelleme


93

Ortam: Python 2.7, matplotlib 1.3, IPython notebook 1.1, linux, chrome. Kod, tek bir giriş hücresindedir.--pylab=inline

Bir akışı kullanmak ve her 5 saniyede bir grafiği dinamik olarak güncellemek için IPython not defterini ve pandaları kullanmak istiyorum.

Verileri metin biçiminde yazdırmak için yalnızca print deyimini kullandığımda, mükemmel çalışıyor: çıktı hücresi verileri yazdırmaya ve yeni satırlar eklemeye devam ediyor. Ancak verileri çizmeye çalıştığımda (ve sonra bir döngüde güncellemeye çalıştığımda), çizim asla çıkış hücresinde görünmüyor. Ancak döngüyü kaldırırsam, sadece bir kez çizin. İyi çalışıyor.

Sonra basit bir test yaptım:

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)

İşlemi manuel olarak kesene kadar çıktı hiçbir şey göstermeyecek (ctrl + m + i). Ve onu kestikten sonra, arsa birden çok üst üste binen çizgi olarak doğru şekilde görünüyor. Ama gerçekten istediğim şey, her 5 saniyede bir ortaya çıkan ve güncellenen bir olay örgüsüdür (veya plot()işlev her çağrıldığında, tıpkı yukarıda bahsettiğim print deyimi çıktıları gibi, bu iyi çalışıyor). Sadece hücre tamamen bittikten sonra son grafiği göstermek istediğim şey DEĞİL.

Hatta her birinin arkasına açıkça draw () fonksiyonu eklemeye çalıştım plot(), vs. Hiçbiri çalışmıyor. IPython not defterinde bir hücre içindeki bir for / while döngüsü ile bir grafiği dinamik olarak nasıl güncelleyeceğinizi merak edin.

Yanıtlar:


123

kullanmak IPython.displaymodülü:

%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)

4
bu pürüzsüz bir seçenek değil, arsa, hücre aralarında yukarı ve aşağı giderken sıfırdan yeniden oluşturuldu
denfromufa

3
Eklemek clear_output(wait=True)bu sorunu çözer. Aşağıdaki wabu'nun cevabına bakın.
ahwillia

3
%matplotlib nbaggOynamak için canlı bir figür veren bu günlerde daha iyisini yapabilirsiniz .
tacaswell

@tcaswell Bunu nbaggbaşarmak için nasıl kullanıldığını soran yeni bir soru ekledim . (Cevaplamakla ilgileniyorsanız size ping atıyorum.) Stackoverflow.com/questions/34486642/…
Nathaniel

3
bu işe yarar ama aynı zamanda basılı ölçüler gibi hücredeki her şeyi yok eder. Sadece arsayı güncellemenin ve diğer her şeyi yerinde tutmanın bir yolu var mı?
KIC

31

Sen daha da ekleyerek bu artırabilir wait=Trueiçin clear_output:

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

1
+1. Bu çok önemli. HYRY'nin cevabının bu bilgi ile güncellenmesi gerektiğini düşünüyorum.
ahwillia

5
Bu iyidir, ancak baskı çıktısını temizlemenin can sıkıcı yan etkisine de sahiptir.
Peter

31

HYRY'nin cevabında birkaç gelişme var :

  • Hücre kesildiğinde iki yerine tek bir olay örgüsüne sahip olabilmeniz için displayönce arayın clear_output.
  • catch the KeyboardInterrupt, böylece hücre çıktısının traceback ile karışmaması için.
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

7
Gerçekten, ÖNCEdisplay.display(gcf()) gitmeli display.clear_output(wait=True)
herrlich10

Teşekkürler @csta. Ekledim.
Tom Phillips

@ herrlich10 Neden daha displayönce aranmalı clear_output? Bunu tersi yapmak yerine önce çıktıyı temizleyip sonra yeni verileri görüntülemeniz gerekmez mi?
Jakub Arnold

1
Grafik güncellemelerinde hala bir ekran titremesi alıyorum, ancak her zaman değil. Bunun için bir çözüm var mı?
MasayoMusic

3

Burada yayınlanan diğer çözümlere etiket eklemek, her döngüde yeni etiketler eklemeye devam edecektir. Bununla başa çıkmak için arsa ile temizleyinclf

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())


4
Teşekkürler plt.clf()çalışır. Ancak, güncellemelerden kaynaklanan titremeden kurtulmanın bir yolu var mı?
MasayoMusic

2

Fonksiyonu eklemeyi show()veya gcf().show()sonrasını deneyin plot(). Bunlar mevcut rakamı güncellenmeye zorlar (gcf () mevcut şekil için bir referans döndürür).


2
Teşekkürler. gcf (). show () da çalışır. Aynı incir üzerindeki şeyleri göstermek için HYRY tarafından önerilen clear_output () eklemeniz gerekiyor
user3236895

Bu, "display.display (pl.gcf ())" öğesine ek olarak mı?
MasayoMusic

0

Bunu böyle yapabilirsin. Liste olarak x, y'yi kabul eder ve bir dağılım grafiği artı aynı grafik üzerinde doğrusal bir eğilim çıkarır.

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();

sadece live_plot(x, y)bir döngü içinde aramanız gerekir . İşte nasıl göründüğü: görüntü açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.