首页 > 编程语言 >python动画教程|Animations using Matplotlib-官网教程程序解读

python动画教程|Animations using Matplotlib-官网教程程序解读

时间:2024-09-01 14:55:32浏览次数:12  
标签:定义 v02 python 矩阵 Matplotlib v0 Animations ax z2

随着python学习的深入,我们不可避免进入画图模块matplotlib,也不可避免会遇到制作动画的需求。

【1】官网教程

如何学习python制作动画,最简单的就是直奔官网:

https://matplotlib.org/stable/users/explain/animations/animations.html#animations

它给出很长的代码,下面是除引入numpy、matplotlib模块之外的部分:

图1

但是官网版本并不具备中文注释,为方便大家快速学习,本期就直接对官网教程自带的代码进行一次添加注释工作,期待能对大家的学习带来便利。

【2】程序模块引入

打开【1】中官网教程会发现,动画制作的前置条件包括:

【a】用数学计算模块numpy生成函数;

【b】用函数绘图模块matplotlib为函数绘图;

【c】用animation模块将matplotlib为函数绘的图形变成动态输出。

官网程序如下:

import matplotlib.pyplot as plt
import numpy as np

import matplotlib.animation as animation

增加注释后变成:

import matplotlib.pyplot as plt   #引入 matplotlib模块,用于绘图
import numpy as np  #引入 numpy模块,用于生成函数

import matplotlib.animation as animation #引入 animation模块,用于生成动画

【3】函数定义代码解读

先查看第一段代码:

fig, ax = plt.subplots()
t = np.linspace(0, 3, 40)
g = -9.81
v0 = 12
z = g * t**2 / 2 + v0 * t

v02 = 5
z2 = g * t**2 / 2 + v02 * t

在这里,需要先说明fig,ax=plt.subplots()的含义:

追溯至官网的入门教程,我们将会看到:

Quick start guide — Matplotlib 3.9.2 documentation

这里的fig,ax=plt.subplots()就是指画一个图,有一个坐标轴。

官网教程还给出了一些测试案例,我们尝试把这段代码直接输出,可参考下输代码:

import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()             # an empty figure with no Axes
fig, ax = plt.subplots()       # a figure with a single Axes
plt.show() #输出图片

运行后:

图2

此时可将初始部分代码解读如下:

fig, ax = plt.subplots()   #定义一个带坐标轴的空图形
t = np.linspace(0, 3, 40)  #定义自变量t的范围是(0,3),中间去40个数,但不包含3
g = -9.81 #定义常数g=-9.81
v0 = 12 #定义常数v0=12
z = g * t**2 / 2 + v0 * t #定义函数z = g * t**2 / 2 + v0 * t ,这是匀加速运动位移时间公式

v02 = 5 #定义常数v02 = 5
z2 = g * t**2 / 2 + v02 * t #定义函数z2 = g * t**2 / 2 + v02 * t ,这是匀加速运动位移时间公式

【4】函数图形输出代码解读

继续解读:

scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s')
line2 = ax.plot(t[0], z2[0], label=f'v0 = {v02} m/s')[0]
ax.set(xlim=[0, 3], ylim=[-4, 10], xlabel='Time [s]', ylabel='Z [m]')
ax.legend()

式中,第一行scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s')的意思是绘制散点图,t[0]代表t的第0个取值0,z[0]代表z的第0个取值0,c指颜色(具体的,“b”代表blue即蓝色),s指散点的大小,label就是指图例。

看不懂的最快解决办法,就是尝试把代码输出。我们先改写为下述代码:

import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()       # a figure with a single Axes
t = np.linspace(0, 3, 40)  #定义自变量t的范围是(0,3),中间去40个数,但不包含3
g = -9.81 #定义常数g=-9.81
v0 = 12 #定义常数v0=12
z = g * t**2 / 2 + v0 * t #定义函数z = g * t**2 / 2 + v0 * t ,这是匀加速运动位移时间公式

v02 = 5 #定义常数v02 = 5
z2 = g * t**2 / 2 + v02 * t #定义函数z2 = g * t**2 / 2 + v02 * t ,这是匀加速运动位移时间公式
scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s')
ax.legend() #输出图例
plt.show() #输出图形

运行后的输出结果为:

 

图3

可见输出点(0,0)对应(t[0],z[0])。

类似的,在上述代码中间补充一行

line2 = ax.plot(t[0], z2[0], label=f'v0 = {v02} m/s')[0] #输出(t[0],z2[0])

变成:

import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()       # a figure with a single Axes
t = np.linspace(0, 3, 40)  #定义自变量t的范围是(0,3),中间去40个数,但不包含3
g = -9.81 #定义常数g=-9.81
v0 = 12 #定义常数v0=12
z = g * t**2 / 2 + v0 * t #定义函数z = g * t**2 / 2 + v0 * t ,这是匀加速运动位移时间公式

v02 = 5 #定义常数v02 = 5
z2 = g * t**2 / 2 + v02 * t #定义函数z2 = g * t**2 / 2 + v02 * t ,这是匀加速运动位移时间公式
scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s') #输出(t[0],z[0])
line2 = ax.plot(t[0], z2[0], label=f'v0 = {v02} m/s')[0] #输出(t[0],z2[0])
ax.legend() #输出图例
plt.show() #输出图形

运行后的输出结果为:

图4

虽然只看见一个点,但实际上的输出点(0,0),同时对应(t[0],z[0])和(t[0],z2[0])。 

剩下部分的as.set部分为对坐标轴进行属性设置,对此不再单独输出,将整个函数图形输出代码增加注释如下:

fig, ax = plt.subplots()       # a figure with a single Axes
t = np.linspace(0, 3, 40)  #定义自变量t的范围是(0,3),中间去40个数,但不包含3
g = -9.81 #定义常数g=-9.81
v0 = 12 #定义常数v0=12
z = g * t**2 / 2 + v0 * t #定义函数z = g * t**2 / 2 + v0 * t ,这是匀加速运动位移时间公式

v02 = 5 #定义常数v02 = 5
z2 = g * t**2 / 2 + v02 * t #定义函数z2 = g * t**2 / 2 + v02 * t ,这是匀加速运动位移时间公式
scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s') #输出(t[0],z[0])
line2 = ax.plot(t[0], z2[0], label=f'v0 = {v02} m/s')[0] #输出(t[0],z2[0])
ax.set(xlim=[0, 3], ylim=[-4, 10], xlabel='Time [s]', ylabel='Z [m]') #设置坐标轴大小和名称
ax.legend() #输出图例
plt.show() #输出图形

【5】update函数代码解读

继续解读:

def update(frame):
    # for each frame, update the data stored on each artist.
    x = t[:frame]
    y = z[:frame]
    # update the scatter plot:
    data = np.stack([x, y]).T
    scat.set_offsets(data)
    # update the line plot:
    line2.set_xdata(t[:frame])
    line2.set_ydata(z2[:frame])
    return (scat, line2)

这里的自定义函数update,引入了一个参数frame,因为这个参数此时第一次出现。它的赋值将在外部调用update函数的时候完成。

此外定义了矩阵x,它是一个由t组成的矩阵;定义了矩阵y,是z矩阵。

然后定义了data矩阵,它调用了numpy中的stack函数,让矩阵x和y先叠加在一起,然后再通过.T做了一次转置。为了形象理解np.stack([x,y]).T,在编辑器尝试输入以下代码:

import matplotlib.pyplot as plt #引入matplotlib模块
import numpy as np #引入numpy模块
x=np.linspace(0,3,3,dtype=int) #定义x矩阵
y=np.linspace(5,8,3,dtype=int) #定义y矩阵
data=np.stack([x,y]) #将x矩阵和y矩阵叠放在一起
dataT=np.stack([x,y]).T #将x矩阵和y矩阵叠放在一起,然后转置
print('x=',x) #输出x矩阵
print('y=',y) #输出y矩阵
print('data=',data) #输出data矩阵
print('dataT=',dataT) #输出dataT矩阵

运行后输出结果为:

图5

然后散点量scat,它通过调用scat.set_offsets(data)将data里面的数据按照顺序输出。

此后的   line2.set_xdata(t[:frame])和line2.set_ydata(z2[:frame])相对简单,将t矩阵作为x输出,z2矩阵最为y输出。

综上所述有:

def update(frame):   #定义update函数
    # for each frame, update the data stored on each artist.
    x = t[:frame]  #定义矩阵x,由t构成的一维数组
    y = z[:frame]  #定义矩阵y,由z构成的一维数组
    # update the scatter plot:
    data = np.stack([x, y]).T #定义矩阵data,将矩阵x,y叠加后转置
    scat.set_offsets(data)  #将矩阵data输出为散点图
    # update the line plot:
    line2.set_xdata(t[:frame]) #将矩阵t设置为x
    line2.set_ydata(z2[:frame]) #将矩阵z2设置为y
    return (scat, line2) #返回scat和line2

【6】update函数代码解读

继续解读,此时只剩最后一行代码:       

ani = animation.FuncAnimation(fig=fig, func=update, frames=40, interval=30)
plt.show()

这里就是使用animation.FuncAnimation模块,反复调用update函数,给frames赋值40,但是我们从官网的animation.FuncAnimation模块中,并没有发现interval应该是哪一个参数。

matplotlib.animation.FuncAnimation — Matplotlib 3.9.2 documentation

为进一步理解interval的意义,最简单的办法就是改变interval的值,看输出结果如何变化。

首先,直接按照interval=30输出,然后,设置interval=0.0030,现实测试发现不会输出结果,只不过是输出变快了。

图6

至此,最后一行代码增加注释后为:

ani = animation.FuncAnimation(fig=fig, func=update, frames=40, interval=30) #调用undape函数输出动画
plt.show() #画图

【7】完整版注释

综上所述,完整版代码注释为:

import matplotlib.pyplot as plt  #引入 matplotlib模块,用于绘图
import numpy as np  #引入 numpy模块,用于生成函数
import matplotlib.animation as animation #引入 animation模块,用于生成动画

fig, ax = plt.subplots()  #定义一个带坐标轴的空图形
t = np.linspace(0, 3, 40) #定义自变量t的范围是(0,3),中间去40个数,但不包含3
g = -9.81 #定义常数g=-9.81
v0 = 12 #定义常数v0=12
z = g * t**2 / 2 + v0 * t #定义函数z = g * t**2 / 2 + v0 * t ,这是匀加速运动位移时间公式

v02 = 5 #定义常数v02 = 5
z2 = g * t**2 / 2 + v02 * t#定义函数z2 = g * t**2 / 2 + v02 * t ,这是匀加速运动位移时间公式

scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s')#输出(t[0],z[0])
line2 = ax.plot(t[0], z2[0], label=f'v0 = {v02} m/s')[0] #输出(t[0],z2[0])
ax.set(xlim=[0, 3], ylim=[-4, 10], xlabel='Time [s]', ylabel='Z [m]') #设置坐标轴大小和名称
ax.legend() #输出图例


def update(frame): #定义update函数
    # for each frame, update the data stored on each artist.
    x = t[:frame]  #定义矩阵x,由t构成的一维数组
    y = z[:frame]  #定义矩阵y,由z构成的一维数组
    # update the scatter plot:
    data = np.stack([x, y]).T #定义矩阵data,将矩阵x,y叠加后转置
    scat.set_offsets(data)  #将矩阵data输出为散点图
    # update the line plot:
    line2.set_xdata(t[:frame]) #将矩阵t设置为x
    line2.set_ydata(z2[:frame]) #将矩阵z2设置为y
    return (scat, line2) #返回scat和line2


ani = animation.FuncAnimation(fig=fig, func=update, frames=40, interval=300) #调用undape函数输出动画
plt.show() #画图

【8】总结

本文对matplotlib官网中的animation动画制作模块进行了示例程序解读,解读过程中对不理解的部分进行了展开探索,非常适用于动画制作初学者学习,对新手小白友好。

标签:定义,v02,python,矩阵,Matplotlib,v0,Animations,ax,z2
From: https://blog.csdn.net/weixin_44855046/article/details/141759108

相关文章

  • 【15.5 python中,wxPython框架的事件处理】
    python中,以wxPython框架为例,介绍一下事件处理在wxPython中,事件处理是构建交互式应用程序的关键部分。用户与图形用户界面(GUI)中的元素(如按钮、文本框等)交互时,会产生事件(如点击、输入文本等)。wxPython提供了一套机制来捕获这些事件,并对它们作出响应。事件处理的基本步骤......
  • 【Python数据可视化】matplotlib库的基本配置
    1.1matplotlib的介绍(1)安装anaconda环境:自带matplotlib,无需另外安装其他Python环境:1.win+R输入cmd进入控制台。2.查看是否有pip(下载Python解释器会自带):pip--version3.更新一下pip......
  • [开题报告]flask框架郴州市高校宿舍管理系统【开题+程序+论文】(python+程序+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着郴州市高等教育的快速发展,高校学生规模不断扩大,宿舍管理成为高校后勤管理中的重要环节。传统的手工记录和管理方式已难以满足日益增长......
  • [开题报告]flask框架宠物寄养系统a769y(程序+论文+python)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着现代生活节奏的加快,宠物已成为许多家庭不可或缺的一员,它们不仅带来了欢乐与陪伴,更成为了人们情感寄托的重要对象。然而,由于工作、旅行......
  • [开题报告]flask框架宠物系统(程序+论文+python)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着城市化进程的加速和人们生活水平的提高,宠物已成为现代家庭中不可或缺的一员,它们不仅为人们带来欢乐与陪伴,还促进了人与自然的和谐共处......
  • 【Python】如何使用pip,安装第三方库和qrcode、xlrd库的使用
    第三方库第三方库就是别人已经实现好了的库,我们可以拿过来直接使用虽然标准库已经很强大了,但是终究是有限的,而第三方库可以视为是集合了全世界Python程序猿的智慧,可以说是几乎无穷无尽使用pippip是Python内置的包管理器所谓包管理器就类似于我们平时使用的手机......
  • python 写一个工具, 上传到 pypi
    起因把自己的图片工具,整理为一个库,package,然后发布出去!就像是一个人喜欢搜集贝壳,现在整理一下,用一根线把好看的贝壳串起来,做成一个项链。整理记录是很有必要的。比如写一个pythonpackage.我之前明明做过(2022年)。项目代码:假设项目代码已经写好了,下面是打包发布......
  • [Python手撕]LRU
    classNode:def__init__(self,key=0,value=0):self.key=keyself.value=valueself.prev=Noneself.next=NoneclassLRUCache:def__init__(self,capacity:int):self.capacity=capacityself.......
  • [Python手撕]LFU
    classNode:def__init__(self,key=0,val=0,pre=None,next=None,fre=0,tail=None):self.key=keyself.val=valself.pre=preself.next=nextself.fre=freself.tail=tailclassLFUCache:d......
  • python读取txt文本文件-批量更改mysql数据库中一批用户的用户名的python脚本保存及转
    一、python读取txt文本文件-批量更改mysql数据库中一批用户的用户名的python脚本保存    做一个简单的事:使用python读取一个txt文件,里面存储着N行用户id,需要一行行读取后再读取另一个存储用户昵称的txt文件,判断昵称是否有重复,如果没有重复就将数据库中的当前uid用户的昵称......