matplotlib
的動畫一直是一個強大但使用頻率不高的功能,究其原因,
一方面展示動畫需要一定的媒介,沒有圖形和文字展示方便;
二來大家更關心的是分析結果的最終圖表,圖表的動態展示則沒有那麼重要。
不過,隨著短影片的興起,在短影片平臺上展示動畫變得非常容易,
所以,我們發現有越來越多的資料分析動畫(比如各種橫向條形圖的排名等等)出現在了短影片平臺上。
透過動畫來展示資料和模型的變化過程,可使資料的視覺化更加生動形象,
隨著各種平臺的興起,matplotlib
的動畫功能也因此有了更多的用武之地。
1. 動畫示例
介紹matplotlib
的動畫功能之前,先看用matplotlib
製作的兩個簡單的的動畫示例。
1.1. 單個動畫
首先是單個動畫,繪製一個正弦曲線。
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
x = np.linspace(-8, 8, 100)
y = np.sin(x)
fig, ax = plt.subplots()
(g,) = ax.plot(x, y)
def update(frame):
y = np.sin(x[:frame])
g.set_data(x[:frame], y)
animation.FuncAnimation(fig, update, interval=50, frames=len(x))
1.2. 組合動畫
除了單個動畫之外,組合動畫也簡單,下面的示例中,
先繪製一個正弦曲線,然後一個點沿著曲線運動,隨著這個點,繪製正弦曲線的切線。
x = np.linspace(-8, 8, 100)
f = lambda x: np.sin(x / 2)
fig, ax = plt.subplots()
fig.set_size_inches(8, 4)
ax.plot(x, f(x), 'lightblue')
(point,) = ax.plot(x[0], f(x[0]), "r", alpha=0.4, marker="o")
(line,) = ax.plot([0], [0], "g", linewidth=3)
#繪製切線
def tangent_line(x0, y0):
h = 1e-4
num_min = f(x0 - h)
num_max = f(x0 + h)
k = (num_max - num_min) / (2 * h)
xs = np.linspace(x0 - 0.5, x0 + 0.5, 100)
ys = y0 + k * (xs - x0)
return xs, ys
#移動切點
def move_point(frame):
point.set_data([x[frame]], [f(x[frame])])
xs, ys = tangent_line(x[frame], f(x[frame]))
line.set_data(xs, ys)
animation.FuncAnimation(fig, move_point, interval=50, frames=len(x))
2. 動畫函式
matplotlib
的動畫函式主要有兩種,它們的動畫原理差別很大,
瞭解它們之間的區別,才能根據自己的場景選擇合適的動畫函式。
2.1. FuncAnimation
上一節的示例中使用的就是FuncAnimation
,它的動畫原理是透過回撥函式,不斷重繪圖形,已達到動畫的效果。
主要的引數有:
- 畫布:比如上面第一個示例中的
fig
- 回撥函式:比如上面第一個示例中的
update
- 呼叫回撥函式的間隔:比如上面第一個示例中的
interval=50
,單位是毫秒 - 呼叫回撥函式的次數:比如上面第一個示例中的
frames=len(x)
簡單來說,也就是FuncAnimation
函式每隔interval
毫秒,呼叫一次update
,一共呼叫frames
次。``
2.2. ArtistAnimation
ArtistAnimation
函式的原理則是先準備好每一幀的資料,然後繪製按照一定的時間間隔,
繪製每一幀資料對應的影像。
比如上面的示例一樣的正弦曲線,用ArtistAnimation
函式繪製的話:
points = np.linspace(-8, 8, 100)
fig, ax = plt.subplots()
frames = []
for i in range(50):
x = points[:i]
y = np.sin(x)
g = ax.plot(x, y)
frames.append(g)
animation.ArtistAnimation(fig, frames, interval=50)
ArtistAnimation
的主要引數:
- 畫布:比如上面示例中的
fig
- 每一幀的資料:比如上面示例中的
frames
- 每一幀的間隔:比如上面示例中的
interval=50
,單位是毫秒
ArtistAnimation
沒有回撥函式,只要準備好每一幀的資料,它會按照時間間隔繪製每一幀的資料。
3. 動畫匯出
最後,是動畫的匯出,常用的兩種格式是MP4
和GIF
。
如果安裝了 ffmpeg
,那麼匯出這兩種格式就很簡單了。
3.1. 匯出mp4
#前面部分省略。。。
anim = animation.FuncAnimation(fig, update, interval=50, frames=len(x))
anim.save("./output.mp4", writer='ffmpeg')
匯出的檔名字尾 mp4
,則可以匯出影片。
這裡的writer
引數用ffmpeg
。
3.2. 匯出GIF
同樣,匯出gif
也一樣,檔名的字尾 gif
即可。
#前面部分省略。。。
anim = animation.FuncAnimation(fig, update, interval=50, frames=len(x))
anim.save("./output.gif", writer='ffmpeg')
當然,也可以不用ffmpeg
,比如,如果安裝了imagemagick
,這裡的writer
也可以用imagemagick
。
#前面部分省略。。。
anim = animation.FuncAnimation(fig, update, interval=50, frames=len(x))
anim.save("./output.gif", writer='imagemagick')