这里的关键是使用Collection。在您的情况下,您想创建一个PatchCollection。
Matplotlib 通过使用集合来优化绘制许多相似的艺术家。它比单独绘制每个要快得多。此外,该情节不会包含成千上万的个人艺术家,只有一个收藏。这加快了每次绘制情节时需要对每个艺术家进行的许多其他杂项操作。
scatter 实际上比您当前的方法快很多,因为它会添加一个集合而不是单独的艺术家。但是,它也会绘制尺寸不在数据坐标中的标记。
要解决这个问题,您可以使用与 scatter 相同的方法,但手动创建集合。
举个例子:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.collections
num = 5000
sizes = 0.2 * np.random.random(num)
xy = 50 * np.random.random((num, 2))
# Note that the patches won't be added to the axes, instead a collection will
patches = [plt.Circle(center, size) for center, size in zip(xy, sizes)]
fig, ax = plt.subplots()
coll = matplotlib.collections.PatchCollection(patches, facecolors='black')
ax.add_collection(coll)
ax.margins(0.01)
plt.show()
这对我来说非常顺利。只是为了证明圆圈在数据坐标中,注意如果我们放大一个窄矩形会发生什么(注意:这假设绘图的方面设置为auto):
如果您真的很注重速度,可以按照@tcaswell 的建议使用EllipseCollection。
EllipseCollection 只会创建 一个 路径,但会在绘制时将其缩放并转换为您指定的位置/大小。
缺点是虽然大小可以在数据坐标中,但圆始终是圆,即使图的纵横比不是 1。(即圆不会像在上图)。
优点是速度快。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.collections
num = 5000
sizes = 0.4 * np.random.random(num)
xy = 50 * np.random.random((num, 2))
fig, ax = plt.subplots()
coll = matplotlib.collections.EllipseCollection(sizes, sizes,
np.zeros_like(sizes),
offsets=xy, units='x',
transOffset=ax.transData,
**kwargs)
ax.add_collection(coll)
ax.margins(0.01)
plt.show()
当我们放大与第二个图相似的区域时,请注意差异。圆圈变大(大小以数据坐标为单位),但保持圆圈而不是拉长。它们不是“数据”空间中圆圈的准确表示。
为了说明时差,下面是使用三种方法中的每一种创建和绘制具有相同 5000 个圆圈的图形的时间:
In [5]: %timeit time_plotting(circles)
1 loops, best of 3: 3.84 s per loop
In [6]: %timeit time_plotting(patch_collection)
1 loops, best of 3: 1.37 s per loop
In [7]: %timeit time_plotting(ellipse_collection)
1 loops, best of 3: 228 ms per loop