这里有几件事需要注意。
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)