簡體   English   中英

如何在 Ipython notebook 中的循環中動態更新繪圖(在一個單元格內)

[英]How to dynamically update a plot in a loop in Ipython notebook (within one cell)

環境:Python 2.7、matplotlib 1.3、IPython notebook 1.1、linux、chrome。 代碼在一個輸入單元格中,使用--pylab=inline

我想使用 IPython notebook 和 pandas 來消耗一個流並每 5 秒動態更新一個圖。

當我只使用 print 語句以文本格式打印數據時,它工作得很好:輸出單元格只是繼續打印數據並添加新行。 但是當我嘗試繪制數據(然后在循環中更新它)時,該圖永遠不會出現在輸出單元格中。 但如果我刪除循環,只需繪制一次。 它工作正常。

然后我做了一些簡單的測試:

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)

在我手動中斷進程 (ctrl+m+i) 之前,輸出不會顯示任何內容。 在我打斷它之后,該圖正確顯示為多條重疊線。 但我真正想要的是一個每 5 秒顯示並更新一次的plot()或者每當調用plot()函數時,就像我上面提到的打印語句輸出的那樣,效果很好)。 僅在單元格完全完成后顯示最終圖表不是我想要的。

我什至嘗試在每個plot()等之后顯式添加 draw() 函數。它們都不起作用。 想知道如何通過 IPython notebook 中一個單元格內的 for/while 循環動態更新繪圖。

使用IPython.display模塊:

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

HYRY 的回答進行了一些改進:

  • clear_output之前調用display以便在單元格中斷時最終得到一個圖,而不是兩個圖。
  • 捕獲KeyboardInterrupt ,這樣單元格輸出就不會被回溯弄得亂七八糟。
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

您可以通過將wait=True添加到clear_output來進一步改進:

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

向此處發布的其他解決方案添加標簽將在每個循環中不斷添加新標簽。 要解決這個問題,請使用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())

我嘗試了很多方法,但我發現這是最簡單和最簡單的方法 -> 添加 clear_output(wait=True),例如,

from IPython.display import clear_output

for i in range(n_iterations):
     clear_output(wait=True)
     x = some value
     y = some value
     plt.plot(x, y, '-r')
     plt.show()

這會覆蓋同一個情節,並給人一種情節動畫的錯覺

嘗試在plot()函數之后添加show()gcf().show() 這些將強制更新當前圖形(gcf() 返回當前圖形的引用)。

你可以這樣做。 它接受 x,y 作為列表,並在同一圖上輸出散點圖和線性趨勢。

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

你只需要在循環內調用live_plot(x, y) 這是它的外觀: 在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM