我已经编写了一个代码以绘制不规则的栅格图(即栅格矩形大小可变的栅格图)。这是下面的最小可重现示例。
问题在于,对于我的示例,在块上循环非常慢(每个图都有很多矩形,并且要绘制很多图)。我试图将坐标转换为元组列表,但这引发了错误。
是否有可能获得补丁。Rectangle返回一个补丁列表,而不是一个列表,因此我可以摆脱补丁循环,并加快代码速度?
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
import matplotlib.colorbar as cbar
fig,ax=plt.subplots(1)
rng=6
plt.ylim(0,rng)
plt.xlim(0,rng)
N = 30
x = np.random.rand(N)*rng
y = np.random.rand(N)*rng
s = np.random.rand(N)
colors=np.random.rand(N)
normal = plt.Normalize(0,1) # my numbers from 0-1
cmap=plt.cm.RdYlBu_r
c=cmap(colors)
for i in range(N):
val=0.5
rect=patches.Rectangle((x[i],y[i]),s[i],s[i],
edgecolor='black',
linewidth = 1,
facecolor = c[i],
)
ax.add_patch(rect)
cax, _ = cbar.make_axes(ax)
cb2 = cbar.ColorbarBase(cax, cmap=cmap,norm=normal)
plt.savefig("test.png")
输出:
答案 0 :(得分:2)
我不确定如何计时,但是对于PatchCollection
来说,这似乎是完美的工作。这样完全可以加速您的图表吗?
编辑:原始测试似乎表明PatchCollection
的性能有所提高,尤其是当N大时。我在这里以N = 1000进行了测试:
%timeit withCollection()
316 ms ± 5.41 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit withoutCollection()
772 ms ± 30.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
完整代码:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
import matplotlib.colorbar as cbar
from matplotlib.collections import PatchCollection
fig,ax=plt.subplots()
rng=6
plt.ylim(0,rng)
plt.xlim(0,rng)
N = 30
x = np.random.rand(N)*rng
y = np.random.rand(N)*rng
s = np.random.rand(N)
colors=np.random.rand(N)
normal = plt.Normalize(0,1) # my numbers from 0-1
cmap=plt.cm.RdYlBu_r
c=cmap(colors)
pat = []
for i in range(N):
rect=patches.Rectangle((x[i],y[i]),s[i],s[i])
pat.append(rect)
col = PatchCollection(pat)
col.set_facecolor(c)
col.set_edgecolor('k')
col.set_linewidth(1.)
ax.add_collection(col)
cax, _ = cbar.make_axes(ax)
cb2 = cbar.ColorbarBase(cax, cmap=cmap,norm=normal)
答案 1 :(得分:2)
一个句子摘要:使用PolyCollection
。
使用集合绘制许多形状肯定比绘制单个矩形更有效。 other answer建议使用PatchCollection
。更加有效的是使用 PolyCollection
。
原因有两个:
我对有关颜色定义(最好让该集合为您完成)和颜色栏(使用该集合,而不是独立的颜色栏)的代码进行了一些修改
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
from matplotlib.collections import PatchCollection, PolyCollection
import matplotlib.transforms as mtrans
PatchCollection:
def patchcoll(N, show=False):
fig,ax=plt.subplots()
rng=6
plt.ylim(0,rng+1)
plt.xlim(0,rng+1)
x = np.random.rand(N)*rng
y = np.random.rand(N)*rng
s = np.random.rand(N)
c = np.random.rand(N)
norm = plt.Normalize(0,1) # my numbers from 0-1
cmap=plt.cm.RdYlBu_r
pat = []
for i in range(N):
rect=patches.Rectangle((x[i],y[i]),s[i],s[i])
pat.append(rect)
col = PatchCollection(pat, cmap=cmap, norm=norm)
col.set_array(c)
col.set_edgecolor('k')
col.set_linewidth(1.)
ax.add_collection(col)
fig.colorbar(col)
if show:
plt.show()
else:
fig.canvas.draw()
plt.close()
PolyCollection:
def polycoll(N, show=False):
fig,ax=plt.subplots()
rng=6
plt.ylim(0,rng)
plt.xlim(0,rng)
x = np.random.rand(N)*rng
y = np.random.rand(N)*rng
s = np.random.rand(N)
c = np.random.rand(N)
norm = plt.Normalize(0,1) # my numbers from 0-1
cmap=plt.cm.RdYlBu_r
offsets = np.c_[x,y]
verts = list(zip([0,1,1,0,0], [0,0,1,1,0]))
col = PolyCollection([verts], sizes=s, offsets=offsets,
transOffset=mtrans.IdentityTransform(),
offset_position="data", cmap=cmap, norm=norm)
col.set_array(c)
col.set_edgecolor('k')
col.set_linewidth(1.)
ax.add_collection(col)
fig.colorbar(col)
if show:
plt.show()
else:
fig.canvas.draw()
plt.close()
单个矩形:
def rectangles(N, show=False):
fig,ax=plt.subplots()
rng=6
plt.ylim(0,rng)
plt.xlim(0,rng)
x = np.random.rand(N)*rng
y = np.random.rand(N)*rng
s = np.random.rand(N)
c = np.random.rand(N)
norm = plt.Normalize(0,1) # my numbers from 0-1
cmap=plt.cm.RdYlBu_r
for i in range(N):
rect=patches.Rectangle((x[i],y[i]),s[i],s[i],
facecolor=cmap(norm(c[i])), edgecolor="k", linewidth=1)
ax.add_patch(rect)
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
fig.colorbar(sm)
if show:
plt.show()
else:
fig.canvas.draw()
plt.close()
全部运行:
patchcoll(30, show=True)
polycoll(30,show=True)
rectangles(30,show=True)
对于N=1000
,我得到
%timeit(rectangles(1000))
757 ms ± 4.26 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit(patchcoll(1000))
184 ms ± 462 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit(polycoll(1000))
58.3 ms ± 146 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
因此,在这种情况下,使用PatchCollection
的效率是单个矩形的3倍,使用PolyCollection
的效率是PatchCollection
的3倍。
使用上面的3种不同方法创建具有N
矩形的图形所需的时间概述: