我有一個不規則的(非矩形)lon/lat網格和一些點在lon/lat座標,它應該對應網格上的點(儘管它們由於數字原因可能會稍微偏離)。現在我需要相應的長/點的指數。高效找到非矩形2D網格上的最近點索引
我寫過一個這樣做的函數,但它真的很慢。
def find_indices(lon,lat,x,y):
lonlat = np.dstack([lon,lat])
delta = np.abs(lonlat-[x,y])
ij_1d = np.linalg.norm(delta,axis=2).argmin()
i,j = np.unravel_index(ij_1d,lon.shape)
return i,j
ind = [find_indices(lon,lat,p*) for p in points]
我很肯定在numpy/scipy中有一個更好(更快)的解決方案。我已經使用了很多搜索引擎,但是迄今爲止我的答案已經不存在了。
任何建議如何有效地找到相應(最近)點的指數?
PS:這個問題出現了另一個問題(click)。
編輯:解
基於@Cong馬雲的回答,我已經找到了以下解決方案:
def find_indices(points,lon,lat,tree=None):
if tree is None:
lon,lat = lon.T,lat.T
lonlat = np.column_stack((lon.ravel(),lat.ravel()))
tree = sp.spatial.cKDTree(lonlat)
dist,idx = tree.query(points,k=1)
ind = np.column_stack(np.unravel_index(idx,lon.shape))
return [(i,j) for i,j in ind]
爲了把這個解決方案,並從Divakar的回答也是一個進入的角度看,這裏有該功能的一些時機在我使用find_indices(以及它是在速度方面的瓶頸)(見上面的鏈接):
spatial_contour_frequency/pil0 : 331.9553
spatial_contour_frequency/pil1 : 104.5771
spatial_contour_frequency/pil2 : 2.3629
spatial_contour_frequency/pil3 : 0.3287
pil0
是我最初的方法,pil1
Divakar's和pil2
/pil3
上面的最終解決方案,其中樹是在pil2
(即pil2
)中即時創建的。對於調用find_indices
的循環的每次迭代)和pil3
(參見其他線程的詳細信息)中的一次。儘管Divakar對我最初的方法進行了改進,使我的速度提高了3倍,但cKDTree以另一個50倍提速將這個提升到了一個全新的水平!將樹的創建移出該功能使事情變得更快。
在您的腳本中,每次調用'find_indices'時都會創建一棵新樹。如果你的網格在呼叫中被修復,那麼你就是在浪費時間重複構建相同的樹。實際上,這個樹的構造是這個函數中最慢的調用。 –
是的,我注意到,這就是我現在正在做的事情。 ;)我會相應地更新答案。謝謝你的評論。 – flotzilla