Mar*_*ath 3 matplotlib bar-chart python-2.7
我想在Python中制作一个动画条形图并以mp4格式保存这个动画.我的问题是保存的视频覆盖中的帧,虽然我使用"blit = True"来告诉动画,只画出帧之间变化的东西.令人惊讶的是,在Python的内置预览中不会出现此问题.这是一个反映我情况的最小值:
import matplotlib.pyplot as plt
from matplotlib import animation
def barlist(n): #That's the list of bars I want to display
C=[]
for k in range(1,6):
C.append(1/float(n*k))
return C
fig=plt.figure()
n=100 #Number of frames
def animate(i):
x=range(1,6)
y=barlist(i+1)
return plt.bar(x,y)
anim=animation.FuncAnimation(fig,animate,repeat=False,blit=True,frames=n,
interval=50)
anim.save('barchart_animated_'+str(n)+'.mp4')
plt.show()
Run Code Online (Sandbox Code Playgroud)
我必须承认,我不太清楚我应该做些什么来消除这个缺陷.我所知道的唯一的例子是条形图没有叠加在框架中(更确切地说,我指的是以下链接的第一个答案的代码):
似乎我不得不告诉动画如何使用set_height-method设置每个帧的每个条的高度.但正如我所说,我真的不知道上面的例子中有什么问题.谢谢你的帮助!
马丁
您在这里遇到的问题是您在动画的每个交互中创建一个新的条形图.它们将逐一添加到图中,但由于它们的高度随着时间的推移而缩小,所以看起来好像只有第一个条形图存在.
有两种方法可以解决这个问题.第一个选项是在绘制新条形图之前清除轴.然而,这将重新调整轴限制,然后应该不断地将其设置为相同的值.
另一种选择是操纵轴上唯一的条形图并调整每个框架的高度.这显示在下面的代码中.
import matplotlib.pyplot as plt
from matplotlib import animation
def barlist(n):
return [1/float(n*k) for k in range(1,6)]
fig=plt.figure()
n=100 #Number of frames
x=range(1,6)
barcollection = plt.bar(x,barlist(1))
def animate(i):
y=barlist(i+1)
for i, b in enumerate(barcollection):
b.set_height(y[i])
anim=animation.FuncAnimation(fig,animate,repeat=False,blit=False,frames=n,
interval=100)
anim.save('mymovie.mp4',writer=animation.FFMpegWriter(fps=10))
plt.show()
Run Code Online (Sandbox Code Playgroud)
Blitting是一种技术,其中图中不变化的所有部分都存储为背景.然后,对于每个动画帧,仅重绘更改的部分.这避免了从头开始重绘背景,从而允许更快的动画.Blitting只会影响屏幕上的动画,因为将动画保存到文件中并不是实时执行的(并且无论如何都不需要).在这里
使用blit=False允许使代码更简单,因为我们不需要关心屏幕上的动画和保存的动画之间的差异 - 它们是相同的.
该enumerate函数从枚举序列中生成索引和对象.我在这里使用它,因为它是在同一循环中获得两者的便捷方式.在这里一点都不重要,你也可以这样做
for i in range(len(barcollection)):
barcollection[i].set_height(y[i])
Run Code Online (Sandbox Code Playgroud)