gpt4 book ai didi

python - 使用 patches.Rectangle 绘制不规则光栅图时避免缓慢循环

转载 作者:太空宇宙 更新时间:2023-11-04 09:34:09 24 4
gpt4 key购买 nike

我写了一段代码来制作不规则的光栅图(即其中光栅矩形的大小是可变的)。下面是一个最小的可重现示例。

问题是在我的示例中循环 block 非常慢(每个图都有很多矩形并且有很多图要制作)。我试图将坐标转换为元组列表,但这引发了错误。

是否有可能获取 patches.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")

输出:

enter image description here

最佳答案

一句话总结:使用PolyCollection


使用集合来绘制许多形状肯定比绘制单个矩形更有效。 other answer建议使用 PatchCollection。更高效的方法是使用 PolyCollection

原因有两个:

  1. 在 PolyCollection 中,您不需要单独创建每个补丁
  2. 仅定义一个形状就足够了,只需指定尺寸、颜色和偏移量即可。

我对有关颜色定义(最好让集合为您完成)和颜色栏(使用集合,而不是独立的颜色栏)的代码做了一些修改

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

补丁集合:

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()

聚合集合:

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 个矩形的图形所需时间的概述:

enter image description here

关于python - 使用 patches.Rectangle 绘制不规则光栅图时避免缓慢循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54463269/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com