【matplotlib基礎】--動畫

wang_yb發表於2023-09-21

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

11.gif

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

11-3.gif

2. 動畫函式

matplotlib的動畫函式主要有兩種,它們的動畫原理差別很大,
瞭解它們之間的區別,才能根據自己的場景選擇合適的動畫函式。

2.1. FuncAnimation

上一節的示例中使用的就是FuncAnimation,它的動畫原理是透過回撥函式,不斷重繪圖形,已達到動畫的效果。
主要的引數有:

  1. 畫布:比如上面第一個示例中的 fig
  2. 回撥函式:比如上面第一個示例中的 update
  3. 呼叫回撥函式的間隔:比如上面第一個示例中的 interval=50,單位是毫秒
  4. 呼叫回撥函式的次數:比如上面第一個示例中的 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)

11-2.gif

ArtistAnimation的主要引數:

  1. 畫布:比如上面示例中的 fig
  2. 每一幀的資料:比如上面示例中的 frames
  3. 每一幀的間隔:比如上面示例中的 interval=50,單位是毫秒

ArtistAnimation沒有回撥函式,只要準備好每一幀的資料,它會按照時間間隔繪製每一幀的資料。

3. 動畫匯出

最後,是動畫的匯出,常用的兩種格式是MP4GIF
如果安裝了 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')

相關文章