Python中的动画条形图 [英] Animated barplot in Python

查看:297
本文介绍了Python中的动画条形图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Python制作动画条形图,并将此动画保存为mp4格式.我的问题是,尽管我使用"blit = True"告诉动画,仅绘制了逐帧变化的内容,但是已保存的视频叠加中的帧仍然存在.出人意料的是,此问题在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):

在matplotlib中动态更新条形图

似乎我必须以某种方式告诉动画它应该如何使用set_height-method设置每一帧的每个条形的高度.但是正如我说的,我真的不知道上面的示例出了什么问题.感谢您的帮助!

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!

马丁

推荐答案

这里的问题是,您在动画的每个插入过程中都会创建一个新的barplot.它们将被逐个添加到图中,但是由于它们的高度随着时间的推移而缩小,因此看起来好像只有第一个条形存在.

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:

划线是一种将图形中所有不变的部分存储为背景的技术.然后,对于每个动画帧,仅重绘变化的部分.这样可以避免从头开始重绘背景,从而可以更快地进行动画处理.涂抹只会影响屏幕上的动画,因为不会将动画实时保存到文件中(而且也不需要这样做).
在这里使用blit=False可以使代码更简单,因为我们不需要关心屏幕上的动画和保存的动画之间的差异-它们是相同的.

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.

enumerate函数从枚举序列中同时产生索引和对象.我在这里使用了它,因为这是在同一循环中同时获取两者的便捷方法.这里一点都不重要,您也可以选择做类似的事情

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

这篇关于Python中的动画条形图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆