使用 matplotlib 绘制动画

在python编程中,用matplotlib绘图工具包绘制动画图形。动画是数据图形化的一种方法,视觉冲击力很强,给人留下了深刻的印象。动画图形或者可交互图形和静态图形相比,对人的诱惑力更强。像股票数据,气象数据,季节性和趋势这样的数据,用动画来表示会让人更容易明白。

matplotlib库的主要特征

  • 有很多后台渲图工具组成
  • 它可以重新生成任何形式的绘图(只需要略做修改)
  • 该工具包历史悠久,比较成熟
  • matplotlib和MATLAB绘图可以转换

然而,matplotlib库也有一些缺点:

  • matplotlib有一个必要的API,这类接口一般比较冗长
  • 有时一些默认的绘图风格比较粗陋
  • 对web图形和交互图形的支持不足
  • 绘制大规模数据和复杂数据的图形比较慢

matplotlib的animation基类和使用条件

matplotlib绘制动画图形就是使用animation基类的方法,它提供了构建动画功能的基本框架,使用的主要接口有两个:

  • FuncAnimation: 通过重复调用函数 func 绘制动画
  • ArtistAnimation: 使用一组固定的Artist对象实现动画效果

这两个接口相比之下,使用FuncAnimation最方便。

使用matplotlib绘制动画需要安装必要的工具包和程序:

  • 需要安装numpy和matplotlib工具包
  • 把程序生成的动画保存为mp4格式或gif格式文件,需要安装 ffmpegimagemagick。

更详细的内容可阅读文章--《如何把python绘制的动态图形保存为gif文件或视频》

实例1:移动的正弦曲线

代码如下:

import numpy as npfrom matplotlib import pyplot as pltfrom matplotlib.animation import FuncAnimationplt.style.use('seaborn-pastel')fig = plt.figure()ax = plt.axes(xlim=(0, 4), ylim=(-2, 2))line, = ax.plot([], [], lw=3)def init():    line.set_data([], [])    return line,def animate(i):    x = np.linspace(0, 4, 1000)    y = np.sin(2 * np.pi * (x - 0.01 * i))    line.set_data(x, y)    return line,anim = FuncAnimation(fig, animate, init_func=init,                               frames=200, interval=20, blit=True)anim.save('sine_wave.gif', writer='imagemagick')

输出的图形结果如下图所示:

实例2:螺旋线动画

代码如下:

import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np plt.style.use('dark_background')fig = plt.figure() ax = plt.axes(xlim=(-50, 50), ylim=(-50, 50)) line, = ax.plot([], [], lw=2) #初始化函数 def init(): #创建空的 plot/frame line.set_data([], []) return line, # 存储x轴和y轴坐标值的列表xdata, ydata = [], [] # 定义动画函数 def animate(i): # 参数 t t = 0.1*i # 根据x和y的值绘制图形 x = t*np.sin(t) y = t*np.cos(t) # 把新的x轴和y轴的值追加到列表 xdata.append(x) ydata.append(y) line.set_data(xdata, ydata) return line, # 制定图形的标题plt.title('Creating a growing coil with matplotlib!') # 隐藏x轴上的数据标识 plt.axis('off') # 调用动画函数 anim = animation.FuncAnimation(fig, animate, init_func=init, frames=500, interval=20, blit=True) # 把动画保存为gif文件 anim.save('coil.gif',writer='imagemagick') 

输出结果如下图所示:

实例3:动画实时更新

绘制股票行情数据、传感器数据等实时图形就需要实时更新动画。

代码如下:

import matplotlib.pyplot as pltimport matplotlib.animation as animationfig = plt.figure()# 创建子图ax1 = fig.add_subplot(1,1,1)def animate(i):    data = open('stock.txt','r').read()    lines = data.split('
')    xs = []    ys = []       for line in lines:        x, y = line.split(',') # Delimiter is comma            xs.append(float(x))        ys.append(float(y))           ax1.clear()    ax1.plot(xs, ys)    plt.xlabel('Date')    plt.ylabel('Price')    plt.title('Live graph with matplotlib')    ani = animation.FuncAnimation(fig, animate, interval=1000) plt.show()

输出结果如下图所示:

实例4:3D动画

代码如下:

from mpl_toolkits.mplot3d import Axes3Dimport matplotlib.pyplot as pltimport pandas as pdimport seaborn as sns# 获取数据url = 'https://python-graph-gallery.com/wp-content/uploads/volcano.csv'data = pd.read_csv(url)# 数据转换df=data.unstack().reset_index()df.columns=["X","Y","Z"]# 转换列名称df['X']=pd.Categorical(df['X'])df['X']=df['X'].cat.codes# 以20个不同的角度,绘制20个图形for angle in range(70,210,2):# 绘制图形    fig = plt.figure()    ax = fig.gca(projection='3d')    ax.plot_trisurf(df['Y'], df['X'], df['Z'], cmap=plt.cm.viridis, linewidth=0.2)    ax.view_init(30,angle)    filename='Volcano/Volcano_step'+str(angle)+'.png'    plt.savefig(filename, dpi=96)    plt.gca()

以上代码创建多个PNG格式文件,要使用ImageMagick把这些图片转换为动画,即在命令行窗口输入下命令:

convert -delay 10 Volcano*.png animated_volcano.gif

输出结果如下图:

实例5:使用Celluloid工具包绘制动画

Celluloid工具包简化了用matplotlib绘制动画的过程,该工具包只创建一个matplotlib的figure对象和camera对象,然后创建的每一帧画面都重复使用这个figure和camera对象,就像是用照相机在抓拍图形。最后,用所有抓拍的画面帧就构成了动画。

安装Celluloid工具包:

pip install celluloid

使用celluloid工具包的绘图实例如下:

实例5-1,代码如下:

from matplotlib import pyplot as pltfrom celluloid import Camerafig = plt.figure()camera = Camera(fig)for i in range(10):    plt.plot([i] * 10)    camera.snap()animation = camera.animate()animation.save('celluloid_minimal.gif', writer = 'imagemagick')

输出结果如下图:

实例5-2:子图,代码如下:

import numpy as npfrom matplotlib import pyplot as pltfrom celluloid import Camerafig, axes = plt.subplots(2)camera = Camera(fig)t = np.linspace(0, 2 * np.pi, 128, endpoint=False)for i in t:    axes[0].plot(t, np.sin(t + i), color='blue')    axes[1].plot(t, np.sin(t - i), color='blue')    camera.snap()    animation = camera.animate()  animation.save('celluloid_subplots.gif', writer = 'imagemagick')

输出结果如下图:


实例5-3:图例,代码如下:

import matplotlibfrom matplotlib import pyplot as pltfrom celluloid import Camerafig = plt.figure()camera = Camera(fig)for i in range(20):    t = plt.plot(range(i, i + 5))    plt.legend(t, [f'line {i}'])    camera.snap()animation = camera.animate()animation.save('celluloid_legends.gif', writer = 'imagemagick')

输出结果如下图:

(本文结束)

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章