2016-06-01 5 views
2

일부 해양 모델 데이터에서 matplotlib를 사용하여 많은 수의 비정규 폴리곤을 그려주는 파이썬 코드가 있습니다.matplotlib : 많은 수의 패치 객체를 만드는 효율적인 방법

난 후, 각각의 세트에 대한하기 matplotlib 패치 객체를 생성 (50 말)

I 형상의 4 개 NumPy와 어레이 (N, 2) N은 다수의 각 패치의 모서리를 정의를 작성하여이를 수행 모서리를 찾아 목록에 추가하십시오. 마지막으로, 패치 목록에서 matplotlib PatchCollection 객체를 만듭니다.

패치 생성이 for 루프에 있기 때문에 문제가 발생합니다. 나는 이것을 멍청한 방송으로 속도를 높이는 방법을 생각하려고 노력해 왔지만, 그것을 깰 수는 없다.

작은 테스트 데이터 세트 (명백하게 빨리 실행 됨)가있는 몇 가지 예제 코드가 있습니다.

import numpy as np 
from matplotlib.collections import PatchCollection 
import matplotlib.pyplot as plt 


# Cell lat/lon centers: 
lons = np.array([ 323.811, 323.854, 323.811, 323.723, 324.162, 324.206, 323.723, 324.162, 323.635, 323.679]) 
lats = np.array([-54.887, -54.887, -54.858, -54.829, -54.829, -54.829, -54.799, -54.799, -54.770, -54.770]) 

# Cell size scaling factors: 
cx = np.array([1,1,1,2,2,2,4,1,2,1]) 
cy = np.array([1,1,1,1,2,2,2,1,2,1]) 

# Smallest cell sizes: 
min_dlon = 0.0439453 
min_dlat = 0.0292969 

# Calculate cell sizes based on cell scaling factor and smallest cell size 
dlon = cx * min_dlon 
dlat = cy * min_dlat 

# calculate cell extnets.... 
x1 = lons - 0.5 * dlon 
x2 = lons + 0.5 * dlon 
y1 = lats - 0.5 * dlat 
y2 = lats + 0.5 * dlat 

# ... and corners 
c1 = np.array([x1,y1]).T 
c2 = np.array([x2,y1]).T 
c3 = np.array([x2,y2]).T 
c4 = np.array([x1,y2]).T 

# Now loop over cells and create Patch objects from the cell corners. 
# This is the bottleneck as it using a slow Python loop instead of 
# fast numpy broadcasting. How can I speed this up? 
ncel = np.alen(lons) 
patches = [] 
for i in np.arange(ncel): 
    verts = np.vstack([c1[i], c2[i], c3[i], c4[i]]) 
    p = plt.Polygon(verts) 
    patches.append(p) 

# Create patch collection from list of Patches 
p = PatchCollection(patches, match_original=True) 

속도를 높일 수있는 방법이 있습니까?

답변

3

모든 폴리곤 (또는 패치)을 생성하는 대신 matplolib.collections으로 콜렉션을 생성하는 것은 어떻습니까? http://matplotlib.org/examples/api/collections_demo.html

그리고하기 matplotlib 문서 읽기 :이 예제 코드는 ~ 10 초를 위해 20 만 개 폴리곤을 추가 http://matplotlib.org/api/collections_api.html?highlight=polycollection#matplotlib.collections.PolyCollection

을 : 여기 예제에서 봐

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib.collections import PolyCollection 
import matplotlib 

npol, nvrts = 200000, 5 
cnts = 100 * (np.random.random((npol,2)) - 0.5) 
offs = 10 * (np.random.random((nvrts,npol,2)) - 0.5) 
vrts = cnts + offs 
vrts = np.swapaxes(vrts, 0, 1) 
z = np.random.random(npol) * 500 

fig, ax = plt.subplots() 
coll = PolyCollection(vrts, array=z, cmap=matplotlib.cm.jet) 
ax.add_collection(coll) 
ax.autoscale() 
plt.show() 

enter image description here

+0

감사합니다. 내 원래 방법은 1 분 20 초 592,425 세포에 대해 실행됩니다. PolyCollection 사용은 20 초 후에 실행됩니다. 중요한 개선. – ccbunney

1

patches도 만들 수 있었다 :

cc=np.stack((c1,c2,c3,c4),1) 
patches = [plt.Polygon(verts) for verts in cc] 

여전히 루프가 포함되지만 루프 밖으로 스택을 이동합니다 (np.stack은 새로운 기능입니다. 버전이 없다면 다시 쓸 수 있습니다.)

시간이 많이 걸릴지 모르겠습니다.

+0

고마워,하지만 대안을 찾으려고하는 것은 파이썬 루프에서 다각형을 만드는 것입니다. – ccbunney

관련 문제