如何生成具有多个值的直方图动画

2023-12-29

迭代更新非常慢,每次只有n+=3,但我的数据有10000个元素。就像,它尝试更新每一帧 n=1,n=2,n=3.. 但 hist 函数确实很耗电。我不知道是否有任何方法可以跳过帧,例如从 n=1 直接跳到 n=500 和 n=1000。

import matplotlib.animation as animation
import numpy as np
import matplotlib.pyplot as plt
n=10000
def update(curr):
    if curr==n:
        a.event_source.stop()
    first_histogram.cla()
    sec_histogram.cla()
    thi_histogram.cla()
    for_histogram.cla()  
    first_histogram.hist(x1[:curr], bins=np.arange(-6,2,0.5))
    sec_histogram.hist(x2[:curr], bins=np.arange(-1,15,1))
    thi_histogram.hist(x3[:curr], bins=np.arange(2,22,1))
    for_histogram.hist(x4[:curr], bins=np.arange(13,21,1))
    first_histogram.set_title('n={}'.format(curr))
fig=plt.figure()
gspec=gridspec.GridSpec(2,2)
first_histogram=plt.subplot(gspec[0,0])
sec_histogram=plt.subplot(gspec[0,1])
thi_histogram=plt.subplot(gspec[1,0])
for_histogram=plt.subplot(gspec[1,1])
a = animation.FuncAnimation(fig,update,blit=True,interval=1,repeat=False)

我怎样才能让它更快?谢谢你!


这里有几件事需要注意。

blit=True清除之间的轴时没有用。它要么不会生效,要么您会在轴上得到错误的刻度标签。 仅当轴限制在帧与帧之间不发生变化时才有用。然而,在正常的直方图中,越来越多的数据被动画化,这必然需要这种情况,否则你的条形要么会超出轴,要么你在开始时看不到低数字。作为替代方案,您可以绘制标准化直方图(即密度图)。

Also, interval=1没有用。在任何普通系统上,您将无法以 1 毫秒的帧速率制作 4 个子图的动画。 Matplotlib 对此来说太慢了。然而,考虑到人脑通常无法解析高于 25 fps(即 40 毫秒)的帧速率。这可能是目标帧速率(尽管 matplotlib 可能无法实现)

所以设置这个的方法很简单

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

x1 = np.random.normal(-2.5, 1, 10000)

def update(curr):
    ax.clear()
    ax.hist(x1[:curr], bins=np.arange(-6,2,0.5))
    ax.set_title('n={}'.format(curr))

fig, ax = plt.subplots()
a = animation.FuncAnimation(fig, update, frames=len(x1), interval=40, repeat=False, blit=False)

plt.show()

如果您想更快地获得列表中的最终项目数,请使用更少的框架。例如。对于快 25 倍的动画,仅显示每 25 个状态,

a = animation.FuncAnimation(fig, update, frames=np.arange(0, len(x1)+1, 25),
                            interval=40, repeat=False, blit=False)

该代码以 11 fps 的帧速率运行(间隔约为 85 ms),因此它比指定的要慢,这意味着我们可以直接设置interval=85.

为了提高帧速率,可以使用位块传输。 为此,您根本不需要更新轴限制。为了进一步优化,您可以预先计算所有要显示的直方图。但请注意,轴限制不应更改,因此我们在开始时设置它们,这会导致不同的绘图。

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

x1 = np.random.normal(-2.5, 1, 10000)
bins = np.arange(-6,2,0.5)
hist = np.empty((len(x1), len(bins)-1))
for i in range(len(x1)):
    hist[i, :], _ = np.histogram(x1[:i], bins=bins) 

def update(i):
    for bar, y in zip(bars, hist[i,:]):
        bar.set_height(y)
    text.set_text('n={}'.format(i))
    return list(bars) + [text]

fig, ax = plt.subplots()
ax.set_ylim(0,hist.max()*1.05)
bars = ax.bar(bins[:-1], hist[0,:], width=np.diff(bins), align="edge")
text = ax.text(.99,.99, "", ha="right", va="top", transform=ax.transAxes)

ani = animation.FuncAnimation(fig, update, frames=len(x1), interval=1, repeat=False, blit=True)

plt.show()

运行此代码给我 215 fps 的帧速率(每帧 4.6 毫秒),因此我们可以设置interval至 4.6 毫秒。

测试于python 3.10 and matplotlib 3.5.1

10000 个样本创建了 40MB 的动画,这超出了发布 gif 的 2MB 限制。

以下动画示例使用 500 个样本,x1 = np.random.normal(-2.5, 1, 500)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何生成具有多个值的直方图动画 的相关文章