파이썬에서 차트를 그리다 보면 실시간 변하면서 움직이는 차트를 그리고 싶을 때가 있습니다.
이럴 때 쓰는 것이 바로 다음의 함수입니다.
matplotlib.pyplot.pause
입니다.
interval이라는 변수를 input으로 받고, interval 초 동안 GUI event loop를 돌리면서 차트의 업데이트를 늦추는 기능을 합니다. 자세항 사항은 matplotlib totorial 을 참고하시면 됩니다.
예제 1. 2차원 Random walk 실시간으로 그리기.
2022.06.25 - [수학의 재미/확률분포] - 술 먹고 걷기(Random Walk) #2: 동서남북 내키는 대로~
여기서 Random Walk에 대한 내용을 다뤘었는데, 술 취한 양반이 동서남북으로 랜덤 하게 움직였을 때, 어디에 도착하는지를 알아봤었습니다. 간단히 복습해보면 동서를 나타내는 확률변수를 $X$ 가 1,-1의 값을, 남북을 나타내는 확률변수가 1, -1의 값을 가진다고 모델링을 하고, 확률이 아래와 같이 $frac14$라고 합시다,
$(X,Y)$ | (1,0) | (-1,0) | (0,1) | (0,-1) |
확률 | $\frac14$ | $\frac14$ | $\frac14$ | $\frac14$ |
방향 | 동 | 서 | 북 | 남 |
그리고 $(X_1 ,Y_1) , (X_2, Y_2), cdots $를 $(X,Y)$의 i.i.d 라고 합시다. $(X,Y)$의 평균은 0 즉, 원점입니다. 이 때,
$$\sum_{i=1}^N (X_i, Y_i)$$
를 하면 바로 이것이 2차원 random walk 가 됩니다.
실시간 그래프를 위하여 아래와 같이 코딩합니다.
import numpy as np
import matplotlib.pyplot as plt
def random_walk_moving():
nSteps = 1000
x = []
y = []
x0, y0 = 0, 0
x.append(x0)
y.append(y0)
a, b = x0, y0
for _ in range(nSteps):
rd = np.random.randint(1, 5)
if rd == 1:
a += 1
b += 1
elif rd == 2:
a += -1
b += 1
elif rd == 3:
a += 1
b += -1
else:
a += -1
b += -1
x.append(a)
y.append(b)
plt.plot(x,y)
plt.pause(0.01)
if __name__ == '__main__':
random_walk_moving()
다른 건 Random Walk 블로그에서 설명을 볼 수 있고, Random walk 진행을 나타내는 변수 $x$,$y$를 갱신하면서
plt.pause(0.01)
를 썼습니다. 즉, 0.01 초동안 그래프의 갱신을 pause 하라는 이야기죠. 결과를 볼까요?
예제 2. 푸리에 급수 관찰하기
sawtooth function이라는 함수가 있습니다.
$$
\begin{align}
& s(x) = \frac{x}{\pi}~~,~~-\pi < x< \pi \\
& s(x+2\pi k ) = s(x)~~,~~ -\pi<x<\pi, k \in \mathbb{Z}
\end{align}
$$
인데요, 이름에서도 느껴지지만 함수 모양 자체가 톱니(sawtooth)처럼 생겼습니다. 주파수 같은 파동을 다루는 이론에서 긴요하게 쓰인다고 알고 있습니다.
이 함수를 푸리에 급수(즉, sin, cos 함수를 이용한 무한급수) 형태로 표시하면 아래와 같습니다.
$$ s(x) = \frac2{\pi} \sum_{n=1}^\infty \frac{(-1)^{n+1}}{n} \sin(nx) $$
즉
$$ s_n(x) = \frac2{\pi} \frac{(-1)^{n+1}}{n} \sin(nx) $$
이라 하면,
$$ s(x) = \sum_{n=1}^\infty s_n(x)$$
라는 얘기죠.
과연 맞는지 coding을 통해 알아보겠습니다.
import numpy as np
import matplotlib.pyplot as plt
def draw_FourierSeries():
x = np.arange(-5 * np.pi, 5 * np.pi, 0.01)
y = np.zeros(len(x))
coeff = 0
for n in range(1, 100):
coeff = (-1) ** (n + 1) / n
y += np.sin(n * x) * coeff * 2 / np.pi
plt.plot(x, y)
plt.pause(1)
# plt.cla()
if __name__ == '__main__':
draw_FourierSeries()
○ x 는 $[-5\pi, 5\pi]$ 구간을 나타냅니다. 0.01 단위로 쪼갰습니다.
○ $s_n$ 을 계산하여 y라는 변수에 계속 더해갑니다.
○ 그래프 변화를 관찰하기 위해 1초 동안 pause 합니다
○ 우선 plt.cla() 는 주석처리합니다.
결과를 보실까요?
결과가 중첩되니까 약간 지저분해 보이죠? 따라서 이전의 함수 그래프를 지우기 위해
plt.cla()
를 사용합니다. 그러면 결과는 아래처럼 보입니다.
참고로
matplotlib.pyplot.cla
Clear the current axes.
입니다.
이처럼 pause를 이용해 움직이는 차트를 그릴 수 있습니다. 시각화에 대한 자신감이 좀 더 생기겠네요.
'파이썬' 카테고리의 다른 글
여러개의 그래프를 한 번에 그리는 예제 (0) | 2023.04.05 |
---|---|
randint를 사용할 땐 주의하라고? (0) | 2022.06.27 |
댓글