python 条形图 动画,Python中的动画条形图

I want to make an animated barchart in Python and save this animation in mp4 format. My problem is that the frames in the saved video overlay, although I use "blit=True" to tell the animation that only the things that change from frame to frame are drawn. Suprisingly, this problem does not occur in the built-in preview of Python.

Here is a minimal that reflects my situation:

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

I must admit that I'm not pretty sure what I should do to remove this flaw. The only example I know of where the bars do not overlay in the frames is here (more exactly, I'm referring to the code of the first answer of the following link):

It seems that I somehow have to tell the animation how it should set the height of each bar at each frame with the set_height-method. But as I said, I don't really know what's wrong in the above example. Thanks for any help!

Martin

解决方案

The problem you have here is that you create a new barplot in every interation of the animation. They will one by one be added to the plot, but since their height is shrinking over time, it may look as though only the first bar is present.

There are two ways to overcome this. First option is to clear the axes before plotting a new bar plot. This however will rescale the axis limits, which should then be constantly set to the same value.

The other option is to manipultate the one and only bar plot in the axes and adapt it's height for every frame. This is shown in the code below.

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

Answers to the questions from the comments:

Blitting is a technique where all the parts of the figure which do not change are stored as a background. Then for each animated frame, only the changing parts are redrawn. This avoids the background to be redrawn from scratch and thus allows for much faster animations. Blitting will only affect the on-screen animation, because saving the animation to a file is not performed in real-time (and doesn't need to anyways).

Using blit=False here allows to make the code more simple because we do not need to care about the differences between the animation on screen and the one saved - they are just the same.

The enumerate function yields both the index as well as the object from the enumerated sequence. I did use it here, because it is a convenient way to obtain both in the same loop. It is not at all important here, you could alternatively do something like

for i in range(len(barcollection)):

barcollection[i].set_height(y[i])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值