본문 바로가기

개발하자

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

반응형

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

에 대한 답변에서는 파이썬 루프 내에서 주피터 노트북 내부의 플롯을 동적으로 업데이트하는 방법에 대한 예시가 제시되어 있다. 그러나 이는 모든 반복에서 플롯을 파괴하고 다시 생성하는 방식으로 작동하며, 스레드 중 하나의 코멘트는 이러한 상황이 정적인 이미지가 아닌 노트에 내장된 상호작용적인 형상을 제공하는 뉴이쉬 마법을 사용함으로써 개선될 수 있다고 언급한다.

그러나 이 놀라운 새로운 기능은 내가 아는 한 완전히 문서화되지 않은 것 같고, 동적으로 플롯을 업데이트하는 데 사용하는 방법에 대한 예를 찾을 수 없다. 따라서 제 질문은, 매트플롯리브에서 동적으로 플롯을 업데이트하는 것은 일반적으로 까다로운 문제이기 때문에, 간단한 작업 예는 큰 도움이 될 것입니다. 주제에 대한 모든 문서에 대한 포인터도 매우 도움이 될 것이다.

제가 원하는 것은 몇 번의 반복에 대해 시뮬레이션 코드를 실행한 다음 현재 상태의 플롯을 그린 다음 몇 번의 반복에 대해 실행한 다음 플롯을 현재 상태를 반영하도록 업데이트하는 것입니다. 그래서 아이디어는 플롯을 그리고 나서 사용자의 어떠한 상호작용 없이, 전체를 파괴하고 다시 만들지 않고 플롯의 데이터를 업데이트하는 것이다.

여기 위의 연결된 질문에 대한 답에서 약간 수정된 코드가 있는데, 이 코드는 매번 전체 그림을 다시 그려서 이를 달성한다. 저는 같은 결과를 얻되 더 효율적으로 사용하고 싶습니다.

%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 Jupyter Extension 패키지가 필요합니다. 를 통해 작업 환경을 설치할 수 있습니다

%matplotlib widget
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)
plt.show()

# run this cell to dynamically update plot
for f in range(5):
    pltsin(ax, ['b', 'r'])
    time.sleep(1)

이것을 놓고, 여기




저는 주피터 실험실을 사용하고 있고 이것은 저에게 효과가 있습니다 (당신의 경우에 맞게 조정).):

from IPython.display import clear_output
from matplotlib import pyplot as plt
import numpy as np
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();

그런 다음 루프에서 사전을 채우고 다음에게 전달합니다:

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

루프 안으로 전화하면 돼요. 다음과 같이 보입니다:




모든 출력을 지우지 않으려면 을 사용하여 핸들을 얻고 이에 사용할 수 있습니다:

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

from IPython import display

def pltsin(ax, *,hdisplay, 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)
    hdisplay.update(fig)


fig,ax = plt.subplots(1,1)
hdisplay = display.display("", display_id=True)

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, colors=['b', 'r'], hdisplay=hdisplay)
    time.sleep(1)
    
plt.close(fig)

(@pneum학에서 온 adapted)




그림의 방법은 현재 그림에 대한 그래프를 동적으로 업데이트합니다:

from matplotlib import pyplot as plt

plt.gcf().canvas.draw()

반응형