Ho una griglia lon/lat irregolare (non rettangolare) e un gruppo di punti in coordinate lon/lat, che dovrebbero corrispondere ai punti sulla griglia (sebbene essi potrebbe essere leggermente fuori per ragioni numeriche). Ora ho bisogno degli indici dei corrispondenti punti lon/lat.Trova in modo efficiente gli indici dei punti più vicini sulla griglia 2D non rettangolare
Ho scritto una funzione che esegue questa operazione, ma è VERAMENTE lenta.
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]
Sono abbastanza sicuro che ci sia una soluzione migliore (e più veloce) in numpy/scipy. Ho già fatto ricerche su Google, ma la risposta mi ha eluso finora.
Qualche suggerimento su come trovare in modo efficiente gli indici dei punti corrispondenti (più vicini)?
PS: questa domanda è emersa da un'altra (click).
Edit: Soluzione
in base alla risposta del @Cong Ma, ho trovato la seguente soluzione:
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]
Per mettere questa soluzione e anche quella dalla risposta di Divakar in prospettiva, qui ci sono alcune temporizzazioni della funzione in cui sto usando find_indices (e dove è il collo di bottiglia in termini di velocità) (vedi link sopra):
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
è il mio approccio iniziale, pil1
Divakar e pil2
/pil3
la soluzione finale sopra, in cui l'albero viene creato al volo in pil2
(ad es. per ogni iterazione del ciclo in cui viene chiamato find_indices
e una sola volta in pil3
(vedere altri thread per i dettagli). Anche se la raffinatezza di Divakar del mio approccio iniziale mi dà un 3x di accelerazione, cKDTree porta questo ad un livello completamente nuovo con un altro 50x di accelerazione! E spostare la creazione dell'albero fuori dalla funzione rende le cose ancora più veloci.
Nel tuo script, stai creando un nuovo albero con ogni chiamata a 'find_indices'. Se la tua griglia è fissa su tutte le chiamate, stai perdendo tempo a costruire lo stesso albero più e più volte. In realtà la costruzione di questo albero è l'unica chiamata più lenta in questa funzione. –
Sì, ho notato, è quello su cui sto lavorando in questo preciso momento. ;) Aggiornerò la risposta di conseguenza. Grazie per l'osservazione. – flotzilla