【问题标题】:Python animation : Large amount of data, slow hist animationPython动画:数据量大,hist动画慢
【发布时间】:2018-11-10 03:36:22
【问题描述】:

迭代更新非常慢,每次只有 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)

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

【问题讨论】:

    标签: python animation matplotlib


    【解决方案1】:

    这里有几点需要注意。

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

    另外,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 毫秒),因此它比指定的要慢,这反过来意味着,我们可以直接设置 interval=85

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

    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 毫秒。

    【讨论】:

    • 谢谢你,你真的做到了,给了我很多见解!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    • 1970-01-01
    • 2013-01-15
    相关资源
    最近更新 更多