TL/DR:如果您在使用 ax.set_... 动画散点图的方法时遇到问题,您可以尝试只清除每帧的绘图(即 ax.clear())并重新- 根据需要绘制事物。这较慢,但当您想在一个小动画中更改很多内容时可能会很有用。
这是一个展示这种“清晰”方法的示例:
import itertools
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
# set parameters
frames = 10
points = 20
np.random.seed(42)
# create data
data = np.random.rand(points, 2)
# set how the graph will change each frame
sizes = itertools.cycle([10, 50, 150])
colors = np.random.rand(frames, points)
colormaps = itertools.cycle(['Purples', 'Blues', 'Greens', 'Oranges', 'Reds'])
markers = itertools.cycle(['o', 'v', '^', 's', 'p'])
# init the figure
fig, ax = plt.subplots(figsize=(5,5))
def update(i):
# clear the axis each frame
ax.clear()
# replot things
ax.scatter(data[:, 0], data[:, 1],
s=next(sizes),
c=colors[i, :],
cmap=next(colormaps),
marker=next(markers))
# reformat things
ax.set_xlabel('world')
ax.set_ylabel('hello')
ani = animation.FuncAnimation(fig, update, frames=frames, interval=500)
ani.save('scatter.gif', writer='pillow')
我从 matplotlib 和其他来源看到的教程似乎没有使用这种方法,但我看到其他人(以及我自己)在这个站点上建议它。我看到了一些优点和缺点,但我会感谢其他人的想法:
优点
- 您可以避免对散点图使用
set_... 方法(即 .set_offsets()、.set_sizes()、...),这些方法的文档更加晦涩难懂(虽然主要的答案会得到你在这里很远!)。另外,对于不同的绘图类型有不同的方法(例如,您使用set_data 表示线条,但不用于散点)。通过清除轴,您可以像 matplotlib 中的任何其他绘图一样确定每帧绘制的元素。
- 更重要的是,不清楚某些属性是否为
set-able,例如标记类型(as commented) 或颜色图。例如,由于标记和颜色图发生了变化,我不知道如何使用ax.set_... 创建上述图。但这对于 ax.scatter() 来说是非常基本的。
缺点
-
可能会慢很多;即清除和重绘一切似乎比
set... 方法更昂贵。所以对于大型动画,这种方法可能有点痛苦。
- 清除轴也会清除轴标签、轴限制、其他文本等内容。因此,这些格式的内容需要包含在
update 中(否则它们将消失)。如果您希望更改某些内容而其他内容保持不变,这可能会很烦人。
当然,速度是个大问题。这是一个显示差异的示例。鉴于此数据:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
np.random.seed(42)
frames = 40
x = np.arange(frames)
y = np.sin(x)
colors = itertools.cycle(['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])
data = [(np.random.uniform(-1, 1, 10) + x[i],
np.random.uniform(-1, 1, 10) + y[i])
for i in range(frames)]
您可以使用set... 方法进行绘图:
fig, ax = plt.subplots()
s = ax.scatter([], [])
ax.set_xlim(-2, frames+2)
ax.set_ylim(min(y) - 1, max(y) + 1)
def update(i):
s.set_offsets(np.column_stack([data[i][0], data[i][1]]))
s.set_facecolor(next(colors))
ani = animation.FuncAnimation(fig, update, frames=frames, interval=100)
ani.save('set.gif', writer='pillow')
或“清除”方法:
fig, ax = plt.subplots()
def update(i):
ax.clear()
ax.scatter(data[i][0], data[i][1], c=next(colors))
ax.set_xlim(-2, frames+2)
ax.set_ylim(min(y) - 1, max(y) + 1)
ani = animation.FuncAnimation(fig, update, frames=frames, interval=100)
ani.save('clear.gif', writer='pillow')
要得到这个数字:
使用%%time,我们可以看到清除和重新绘制需要(超过)两倍的时间:
- 对于
set...:Wall time: 1.33 s
- 明确:
Wall time: 2.73 s
使用frames 参数在不同的尺度上进行测试。对于较小的动画(较少的帧/数据),这两种方法之间的时间差异是无关紧要的(对我来说,有时会导致我更喜欢清除方法)。但对于较大的情况,使用set_... 可以节省大量时间。