酒飲みによる機械学習日記

〜ただの酒好きが、なんとなく流行っている機械学習について語っていきます、たまに金融ネタも〜

Pythonでアニメーション1

はじめに

今回は、可視化の練習の1つとして、グラフを動的に描写してみようと思います。やっぱり変化の様子をみていくことに関しては、動画形式である方がいいと思います!!

参考にしたサイトは、

です!!!

作ったアニメーションはsin波です!(容量の関係で、以下のファイルは定義域が0から5になっています。)

f:id:nts-524:20181008190934g:plain

全コードは最後に添付してあります。

詳しく

流れは以下のようになっています。

  1. 必要モデュールのインストール
  2. figureと、プロット用変数の準備
  3. プロットを更新していく関数の定義
  4. アニメーションの作成及び保存、可視化

1. 必要モデュールのインストール

以下のコマンドでできます!今回は他にもseabornargparseも使っていますが、絶対必要なわけではないです!pillowはPythonの画像処理用のライブラリです。

pip install matplotlib pillow

2. figureと、プロット用変数の準備

figでmatplotlibのfigureを準備して、x, yには空のリストを入れておきます。xyには順番にプロット用のデータを追加していくことになります。

fig = plt.figure()
x = []
y = []

3. プロットを更新していく関数の定義

frameという引数によってxyの値がどんどん追加されていきます。現在はxにはそのままframeの値を、yにはsin(frame)の値を入れています。

plt.cla()で前のプロットをリセットし、xyの値を追加後、plt.plot()で再度プロットしています。

def plot(frame, x_min=args.x_min, x_max=args.x_max):
        """update function for graph"""
        # clean graph
        plt.cla()
        # add data
        x.append(frame)
        y.append(math.sin(frame))
        # replot
        plt.xlim(x_min, x_max)
        plt.ylim(-1, 1)
        plt.plot(x, y)

4. アニメーションの作成及び保存、可視化

変数animeに、作成されたアニメーションが入っています。

  • 引数framesで、先ほど定義したplot()関数へ渡されていく値を準備
  • 引数intervalで何ミリ秒ごとにプロットを更新するかを定義します
  • repeatは繰り返すかを指定します。repeat=Trueの場合は、終点と始点が繋がることになります(つまりsin波的にはおかしいことになってしまいます)。

またanime.save(savepath, writer='pillow')で作成したアニメーションを保存できます。ここでpillowを指定するために、はじめにpip install pillowをしておきました。

画像の時と同じく、plt.show()でwindowが出てくる可視化になります。

anime = animation.FuncAnimation(
        fig, plot,
        interval=10, # [ms]
        frames=np.arange(args.x_min, args.x_max, 0.1),
        repeat=False,
    )
anime.save(args.result, writer='pillow')
plt.show()

ソースコード

# =-=-=-=-=-=-=-=-=-=-=-=- module -=-=-=-=-=-=-=-=-=-=-=-= #
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
import seaborn as sns
import math, os, argparse

sns.set_style('whitegrid')

# =-=-=-=-=-=-=-=-=-=-=-=- main -=-=-=-=-=-=-=-=-=-=-=-= #
def main():
    # argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('--x_min', type=float, default=0.0)
    parser.add_argument('--x_max', type=float, default=10.0)
    parser.add_argument('--result', type=str, default='result/anime.gif')
    args = parser.parse_args()

    # make result directory
    if not os.path.exists('result/'):
        os.makedirs('result/')

    # define plot function
    fig = plt.figure()
    x = []
    y = []
    def plot(frame, x_min=args.x_min, x_max=args.x_max):
        """update function for graph"""
        # clean graph
        plt.cla()
        # add data
        x.append(frame)
        y.append(math.sin(frame))
        # replot
        plt.xlim(x_min, x_max)
        plt.ylim(-1, 1)
        plt.plot(x, y)

    # visualize result
    anime = animation.FuncAnimation(
        fig, plot,
        interval=10, # [ms]
        frames=np.arange(args.x_min, args.x_max, 0.1),
        repeat=False,
    )
    anime.save(args.result, writer='pillow')
    plt.show()

if __name__ == '__main__':
    main()