[python] Jupyter / iPython에서 플롯을 동적으로 업데이트하는 현재 올바른 방법은 무엇입니까?

ipython notebook (하나의 셀 내)의 루프에서 플롯을 동적으로 업데이트하는 방법에 대한 답변에서 Python 루프 내에서 Jupyter 노트북 내부의 플롯을 동적으로 업데이트하는 방법에 대한 예제가 제공됩니다. 그러나 이것은 매 반복마다 플롯을 파괴하고 다시 생성하는 방식으로 작동하며 스레드 중 하나의 주석은 %matplotlib nbagg노트북에 포함 된 대화 형 그림을 제공하는 새로운 마법 을 사용하여이 상황을 개선 할 수 있다고 언급합니다. 정적 이미지보다.

그러나이 멋진 새 nbagg기능은 내가 말할 수있는 한 완전히 문서화되지 않은 것처럼 보이며이를 사용하여 플롯을 동적으로 업데이트하는 방법에 대한 예를 찾을 수 없습니다. 따라서 내 질문은 nbagg 백엔드를 사용하여 Jupyter / Python 노트북의 기존 플롯을 어떻게 효율적으로 업데이트합니까? matplotlib에서 플롯을 동적으로 업데이트하는 것은 일반적으로 까다로운 문제이므로 간단한 작업 예제가 큰 도움이 될 것입니다. 주제에 대한 문서에 대한 포인터도 매우 유용합니다.

내가 원하는 것은 몇 번의 반복에 대해 시뮬레이션 코드를 실행 한 다음 현재 상태의 플롯을 그린 다음 몇 번 더 반복하여 실행 한 다음 반영하도록 플롯을 업데이트하는 것입니다. 현재 상태 등. 따라서 아이디어는 플롯을 그린 다음 사용자의 상호 작용없이 전체를 파괴하고 다시 생성하지 않고 플롯의 데이터를 업데이트하는 것입니다.

다음은 위의 링크 된 질문에 대한 답변에서 약간 수정 된 코드로, 매번 전체 그림을 다시 그려이를 달성합니다. 동일한 결과를 얻고 싶지만 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)



답변

다음은 루프에서 플롯을 업데이트하는 예입니다. 그림의 데이터를 업데이트하고 매번 전체 그림을 다시 그리지 않습니다. 제한된 시뮬레이션 세트를 실행하고 결과를 어딘가에 저장하는 데 관심이 있다면 실행을 차단하지만 문제가되지 않을 수 있습니다.

%matplotlib notebook

import numpy as np
import matplotlib.pyplot as plt
import time

def pltsin(ax, colors=['b']):
    x = np.linspace(0,1,100)
    if ax.lines:
        for line in ax.lines:
            line.set_xdata(x)
            y = np.random.random(size=(100,1))
            line.set_ydata(y)
    else:
        for color in colors:
            y = np.random.random(size=(100,1))
            ax.plot(x, y, color)
    fig.canvas.draw()

fig,ax = plt.subplots(1,1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
for f in range(5):
    pltsin(ax, ['b', 'r'])
    time.sleep(1)

나는 이것을 nbviewer에 올려 놓았습니다.

의 IPython 위젯 버전 nbagg즉,하기 matplotlib 저장소에서 진행중인 작업은 현재됩니다 . 사용 가능한 경우를 사용하는 가장 좋은 방법 일 것입니다 nbagg.

편집 : 여러 플롯을 표시하도록 업데이트 됨


답변

나는 jupyter-lab을 사용하고 있으며 이것은 나를 위해 작동합니다 (귀하의 경우에 적용하십시오).

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

그런 다음 루프에서 사전을 채우고 다음으로 전달합니다 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)

플롯 아래에 몇 개의 셀이 있는지 확인하십시오. 그렇지 않으면 플롯을 다시 그릴 때마다 뷰가 제자리에 고정됩니다.


답변

@Ziofil 대답을 수정하고 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)루프 내부 에서 호출 하면됩니다. 다음과 같이 보입니다.
여기에 이미지 설명 입력


답변