본문 바로가기

Software/Python

Matplotlib에서 그래프를 애니메이션으로 표현하기

Python이든 뭐든 데이터를 시각화하는 것은 항상 필요한 과정입니다. 그런데 그 데이터가 너무 길어 한 화면에 담아보면 구분이 되지 않거나, 시간의 흐름에 대해 약간 강조하고 싶다면 애니메이션 효과를 찾아보게 되죠. 당연히 Matplotlib도 그에 대한 대응을 해주고 있습니다. 추가로 Jupyter Notebook 화면에서 이를 구현하는 예제가 matplotlib에 있길래 이를 잠시 테스트해 보았습니다.^^ 먼저...

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from matplotlib import animation, rc

이렇게 초기화를 하구~~~

fig, ax = plt.subplots()

ax.set_xlim(( 0, 2))
ax.set_ylim((-2, 2))

line, = ax.plot([], [], lw=2)

먼저 그래프의 설정이 있으면 좀 지정해 줍니다. 여기를 실행하면, Jupyter Notebook에서는

이렇게 결과가 빈 그래프로 나오지만, 그건 plot 명령이 들어와서 실행된 것으로 신경쓰지 않아도 됩니다. 그리고

def init():
    line.set_data([], [])
    return (line,)

각 프레임에 적용될 배경 역할을 하는 의미로 초기화 작업을 살짝 해줍니다.

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return (line,)

이게 애니메이션이 구현된 부분인데요. 매번 i를 위상에 곱해서 sine 함수의 위치를 변경시켜줍니다.

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=100, interval=20, blit=True)

그리고 위와 같이 animation을 설정해 주면 됩니다. 그럼에도 불구하고 화면에는 안 나타날 수 있는데요^^ 사용하시는 OS에 맞춰 FFMpeg를 설치해야 합니다. 저는 맥이라서 brew isntall ffmpeg라는 명령으로 손쉽게 진행했구요. 각 OS에 맞는 작업은 [바로가기]로 가서 확인해보시면 됩니다.

rc('animation', html='html5')
anim

그리고 위 명령을 주면 Jupyter Notebook 화면에 

위와 같이 애니메이션 결과가 나타날 것입니다.

하나 더~~~가면...

import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation
import pandas as pd


a = np.random.rand(2000, 3)*10
t = np.array([np.ones(100)*i for i in range(20)]).flatten()
df = pd.DataFrame({"time": t ,"x" : a[:,0], "y" : a[:,1], "z" : a[:,2]})

def update_graph(num):
    data=df[df['time']==num]
    graph._offsets3d = (data.x, data.y, data.z)
    title.set_text('3D Test, time={}'.format(num))

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
title = ax.set_title('3D Test')

data=df[df['time']==0]
graph = ax.scatter(data.x, data.y, data.z)
plt.show()

위 코드는 랜덤하게 scatter하는 것으로

이렇게 결과가 나옵니다. 

from IPython.display import HTML

ani = matplotlib.animation.FuncAnimation(fig, update_graph, 19, interval=400, blit=False)
HTML(ani.to_html5_video())

거기에... 위와 같이 코드를 만들고 나면~ (여기서 처음 것과 달리 IPython.display.HTML을 사용합니다.)

이런 움직임도 볼 수 있습니다. 애니메이션도 update할 내용에 대해서만 잘 정의해 둔다면 크게 어렵지 않네요^^

반응형