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

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


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


是否有可能让 patch.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")


凤凰求蛊
浏览 277回答 2
2回答

慕桂英3389331

一句话总结:用一个PolyCollection。使用集合绘制多个形状肯定比绘制单个矩形更有效。在其他答案建议使用PatchCollection。更有效的是使用PolyCollection.原因有两个:在 PolyCollection 中,您不需要单独创建每个补丁只定义一个形状就足够了,并且只指定大小、颜色和偏移量。我对有关颜色定义(最好让集合为您完成)和颜色条(使用集合,而不是独立的颜色条)的代码进行了一些修改import matplotlib.pyplot as pltimport matplotlib.patches as patchesimport numpy as npfrom matplotlib.collections import PatchCollection, PolyCollectionimport 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)因此,在这种情况下,使用 a 的PatchCollection效率比单个矩形高 3 倍,使用 a 的PolyCollection效率比 a 高 3 倍PatchCollection。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python