在 Python/Matplotlib 中动画“增长”线图

Posted

技术标签:

【中文标题】在 Python/Matplotlib 中动画“增长”线图【英文标题】:Animating "growing" line plot in Python/Matplotlib 【发布时间】:2015-03-20 09:35:59 【问题描述】:

我想制作一组可用于为生长线图制作动画的帧。过去,我一直使用 plt.draw() 和 set_ydata() 来重新绘制随时间变化的 y 数据。这一次,我想画一条“增长”的线,随着时间在图表上移动。因此, set_ydata 不起作用(xdata 正在改变长度)。例如,

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y = np.sin(x)

plt.figure()
for n in range(len(x)):
    plt.plot(x[:n], y[:n], color='k')
    plt.axis([0, 10, 0, 1])
    plt.savefig('Frame%03d.png' %n)

虽然这可行,但随着规模的扩大,它会变得非常缓慢。有没有更快的方法来做到这一点?

【问题讨论】:

您是否有示例(链接)指向您想要重新创建的图形? Python中有一堆动画包可以使用。 @MylesBaker 以下是它的外观示例(对于上面的代码):media.giphy.com/media/3xz2BD48KS3fOGzAJ2/giphy.gif 是否要在公开更多数据时更新图表限制? (即重绘图表)?或者您的域和范围是否已知? 域和范围是已知的。最好我想设置图形、轴和标签,然后只更新数据。如果可以只添加最新的数据点并将它们连接起来,那也很好,例如 plot(x[n-1,n], y[n-1,n], color='k')。 你知道matplotlib的animation.Animate吗?它还可以保存电影。 【参考方案1】:

几点说明:

首先,事情变得越来越慢的原因是您在同一位置绘制越来越多的重叠线。

一个快速的解决方法是每次清除情节:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y = np.sin(x)

plt.figure()
for n in range(len(x)):
    plt.cla()
    plt.plot(x[:n], y[:n], color='k')
    plt.axis([0, 10, 0, 1])
    plt.savefig('Frame%03d.png' %n)

不过,最好同时更新 x 和 y 数据:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots()
line, = ax.plot(x, y, color='k')

for n in range(len(x)):
    line.set_data(x[:n], y[:n])
    ax.axis([0, 10, 0, 1])
    fig.canvas.draw()
    fig.savefig('Frame%03d.png' %n)

如果您想使用动画模块(旁注:blit=True 可能无法在某些后端(例如 OSX)上正常工作,所以如果您有问题,请尝试blit=False):

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

x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots()
line, = ax.plot(x, y, color='k')

def update(num, x, y, line):
    line.set_data(x[:num], y[:num])
    line.axes.axis([0, 10, 0, 1])
    return line,

ani = animation.FuncAnimation(fig, update, len(x), fargs=[x, y, line],
                              interval=25, blit=True)
ani.save('test.gif')
plt.show()

【讨论】:

set_data 解决方案非常优雅。希望我能投票 10 次。 如果保存为视频而不是 .gif 则 ani.save('test.mp4', writer='ffmpeg', codec='h264') 应该替换最后一行。如果您想找出可用的编解码器,请在终端中运行ffmpeg -codec。鉴于您想使用 ffmpeg 作为编写器。 收到此错误 `ValueError: Invalid file object: <_io.bufferedreader name="8"> @JoeKington - 这可能是一个愚蠢的问题,但我能问一下你的num arg 来自哪里吗? (def update(num, x, y, line))。我没有在fargs=[x, y, line] 中看到它。谢谢! @Joe 你能在行前加一个点吗?我正在 3d 中绘制线条形状,我想使用每个列表的最后一个元素 x[-1], y[-1], z[-1]>将头部放在线条的前面>

以上是关于在 Python/Matplotlib 中动画“增长”线图的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python Matplotlib 在 3D 轴上为振动传感器读数创建动画散点图

用Python Matplotlib 制作动画

如何使用 python matplotlib 与另一个代码并行运行动画?

Python Matplotlib FuncAnimation + Saving

如何使用 python/matplotlib 为 3d 绘图设置“相机位置”?

如何在 python/matplotlib 中制作居中气泡图