用Python制作直方图的动画

2024-09-28 19:05:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试随着时间的推移绘制直方图的动画,到目前为止,我得到的代码如下:

import matplotlib.pyplot as plt
import numpy as np
import time
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)

alphab = ['A', 'B', 'C', 'D', 'E', 'F']
frequencies = [1, 44, 12, 11, 2, 10]

pos = np.arange(len(alphab))
width = 1.0     # gives histogram aspect to the bar diagram
ax.set_xticks(pos + (width / 2))
ax.set_xticklabels(alphab)
for bin_idx in np.linspace(0,1000000,100000000):
     t = time.time()
     #Here we just change the first bin, so it increases through the animation.
     frequencies[0] = bin_idx
     line1 =plt.bar(pos, frequencies, width, color='r')
     plt.draw()
     elapsed = time.time() - t
     print elapsed

代码可以工作,但是输出显示在经过一些迭代之后,它会变得比开始时慢得多。有没有一种方法可以加快速度,我们想实时更新它,它运行的过程相当快。在

另外,需要注意的是,我不需要后期处理的动画,我们需要实时更新,所以直方图动画示例不适用于这个特定的过程。在

谢谢


Tags: the代码posimportbintimeasnp
2条回答

我认为您的代码会变慢,因为您没有清除数字,所以每次迭代都会在另一个上面重复柱状图。在

line1 = ...之前添加一个plt.clf()调用将清除现有的图形。在

如果您有较新版本的Matplotlib,则有一个^{} class,它可以帮助减少一些锅炉板代码。(例如,See this page)非常快(~52帧每秒):

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import timeit

clock = timeit.default_timer

fig, ax = plt.subplots()

alphab = ['A', 'B', 'C', 'D', 'E', 'F']
frequencies = [1, 44, 12, 11, 2, 10]

pos = np.arange(len(alphab))
width = 1.0     # gives histogram aspect to the bar diagram
ax.set_xticks(pos + (width / 2))
ax.set_xticklabels(alphab)

rects = plt.bar(pos, frequencies, width, color='r')
start = clock()

def animate(arg, rects):
    frameno, frequencies = arg
    for rect, f in zip(rects, frequencies):
        rect.set_height(f)
    print("FPS: {:.2f}".format(frameno / (clock() - start))) 

def step():
    for frame, bin_idx in enumerate(np.linspace(0,1000000,100000000), 1):
        #Here we just change the first bin, so it increases through the animation.
        frequencies[0] = bin_idx
        yield frame, frequencies


ani = animation.FuncAnimation(fig, animate, step, interval=10,
                              repeat=False, blit=False, fargs=(rects,))
plt.show()

如果没有更新版本的Matplotlib,这里有一个旧的方法。速度稍慢(~45帧每秒):

不要在循环的每次迭代中调用plt.bar。相反,只需调用一次,保存rects返回值,然后调用set_height在循环的后续迭代中修改这些{}的高度。这个技巧(和其他技巧)在Matplotlib Animations Cookbook中解释。在

^{pr2}$

作为比较,在我的机器上,将plt.clf添加到原始代码中,大约达到每秒12帧。在


关于时间安排的一些评论:

通过计算每次通过循环的非常小的时间差,无法获得精确的测量结果。至少在我的电脑上,time.time()的时间分辨率不够好。通过测量一个开始时间并计算开始时间和当前时间之间的大时间差,然后除以帧数,可以得到更精确的测量结果。在

我还将time.time改为timeit.default_timer。在Unix计算机上这两者是相同的,但是在Windows计算机上,timeit.default_timer被设置为time.clock。因此,timeit.default_timer为每个平台选择更精确的计时器。在

相关问题 更多 >