我们有一个包含大量线的绘图。在动画中,我们需要更新线的颜色,但使用嵌套循环对线进行迭代似乎非常耗时。是否存在更好的方法来完成此操作?
以下是我们的代码:
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.animation as animation
# 初始绘图
fig = plt.figure()
ax = plt.subplot(1, 1, 1)
lines = []
for i in range(10):
lines.append([])
for j in range(10):
lines[i].append(ax.plot([i, j], color='0.8'))
lines = np.asarray(lines)
# 更新颜色 10 次
im = []
for steps in range(10):
colors = np.random.random(size=(10, 10))
for i in range(10):
for j in range(10):
lines[i, j][0].set_color(str(colors[i, j]))
plt.draw()
# im.append(ax)
plt.pause(.1)
# ani = animation.ArtistAnimation(fig, im, interval=1000, blit=True, repeat_delay=1000)
plt.show()
同时,我们在尝试将其与动画一起运行时遇到了问题。我们希望将其制作成一个动画,认为这至少在动画开始后可以解决延迟问题,但按照我们当前定义的方式,它不起作用。
- 解决方案
以下是优化解决方案:
解决方案 1:使用 LineCollection
使用 LineCollection 可以更轻松地解决此问题。这样,我们可以将所有颜色设置为单个数组,并且通常可以获得更好的绘图性能。
改进的性能主要是因为集合是 matplotlib 中绘制大量相似对象的一种优化方式。在这种情况下,避免嵌套循环来设置颜色实际上是次要的。
请尝试类似以下内容:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
import matplotlib.animation as animation
lines = []
for i in range(10):
for j in range(10):
lines.append([(0, i), (1, j)])
fig, ax = plt.subplots()
colors = np.random.random(len(lines))
col = LineCollection(lines, array=colors, cmap=plt.cm.gray, norm=plt.Normalize(0, 1))
ax.add_collection(col)
ax.autoscale()
def update(i):
colors = np.random.random(len(lines))
col.set_array(colors)
return col,
# 将此设置为非常短的更新间隔以显示快速绘制。
# 25 毫秒会比 1 毫秒更合理。
ani = animation.FuncAnimation(fig, update, interval=1, blit=True,
init_func=lambda: [col])
# 某些 matplotlib 版本明确需要一个 `init_func` 才能正确显示...
# 理想情况下,我们会在其中完全初始化绘图。为了简单起见,我们只返回艺术家以便 `FuncAnimation` 知道要绘制什么。
plt.show()
解决方案 2:使用生成器表达式
如果您想加快 for 循环的速度,有几种很好的方法可以做到。对于您要执行的操作,最好的方法可能是生成器表达式,如下所示:
iterator = (<variable>.upper() for <samevariable> in <list or other iterable object>)
(有关更多具体信息,请参阅 www.python.org/dev/peps/pe… 和 wiki.python.org/moin/Genera… 上的文档)
还有一些其他非 for 循环方式可以更新颜色,但它们不太可能比生成器更快。您可以为线条创建某种形式的分组,并调用类似以下内容:
lines.update()
这样即可更新所有的线条。