Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用面片绘制不规则光栅图时避免缓慢循环。矩形_Python_Performance_Loops_Matplotlib - Fatal编程技术网

Python 使用面片绘制不规则光栅图时避免缓慢循环。矩形

Python 使用面片绘制不规则光栅图时避免缓慢循环。矩形,python,performance,loops,matplotlib,Python,Performance,Loops,Matplotlib,我已经编写了一个代码来制作一个不规则的光栅图,即光栅矩形的大小是可变的。下面是一个最小的可复制示例 问题是,在块上循环非常慢,对于我的示例,每个图都有很多矩形,并且有很多图要绘制。我试图将坐标转换成元组列表,但出现了一个错误 是否可以获取patches.Rectangle以返回补丁列表,而不是一个,这样我就可以消除补丁上的循环并加快代码的速度 import matplotlib.pyplot as plt import matplotlib.patches as patches import n

我已经编写了一个代码来制作一个不规则的光栅图,即光栅矩形的大小是可变的。下面是一个最小的可复制示例

问题是,在块上循环非常慢,对于我的示例,每个图都有很多矩形,并且有很多图要绘制。我试图将坐标转换成元组列表,但出现了一个错误

是否可以获取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")
输出:


我不知道确切的计时方法,但这似乎是一份完美的工作。这会加速你的图表吗

编辑:粗略的测试似乎显示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) 

我不知道确切的计时方法,但这似乎是一份完美的工作。这会加速你的图表吗

编辑:粗略的测试似乎显示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) 

一句话总结:使用多个集合

使用集合绘制许多形状肯定比绘制单个矩形更有效。建议使用补丁集合。更有效的方法是使用多个集合

原因有两方面:

在多边形集合中,不需要单独创建每个面片 只定义一个形状就足够了,只需指定大小、颜色和偏移。 我对有关颜色定义的代码做了一些修改,最好让集合为您完成,并且颜色栏使用集合,而不是独立的颜色栏

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 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,我得到

因此,在这种情况下,使用PatchCollection比单个矩形的效率高3倍,而使用PolyCollection比PatchCollection的效率高3倍

概述使用上述3种不同方法创建具有N个矩形的图形所需的时间:


一句话总结:使用多个集合

使用集合绘制许多形状肯定比绘制单个矩形更有效。建议使用补丁集合。更有效的方法是使用多个集合

原因有两方面:

在多边形集合中,不需要单独创建每个面片 只定义一个形状就足够了,只需指定大小、颜色和偏移。 我对有关颜色定义的代码做了一些修改,最好让集合为您完成,并且颜色栏使用集合,而不是独立的颜色栏

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 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,我得到

因此,在这种情况下,使用PatchCollection比单个矩形的效率高3倍,而使用PolyCollection比PatchCollection的效率高3倍

概述使用上述3种不同方法创建具有N个矩形的图形所需的时间:


我不确定,但也许a可以解决你的问题。我不确定,但也许a可以解决你的问题。