在 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 FuncAnimation + Saving