Here's a generic vector approach using scipy.spatial.distance.cdist -
import scipy
Run Example -
In [161]: lon Out[161]: array([[-11. , -7.82 , -4.52 , -1.18 , 2.19 ], [-12. , -8.65 , -5.21 , -1.71 , 1.81 ], [-13. , -9.53 , -5.94 , -2.29 , 1.41 ], [-14.1 , -0.04 , -6.74 , -2.91 , 0.976]]) In [162]: lat Out[162]: array([[-11.2 , -7.82 , -4.51 , -1.18 , 2.19 ], [-12. , -8.63 , -5.27 , -1.71 , 1.81 ], [-13.2 , -9.52 , -5.96 , -2.29 , 1.41 ], [-14.3 , -0.06 , -6.75 , -2.91 , 0.973]]) In [163]: lonlat = np.column_stack((lon.ravel(),lat.ravel())) In [164]: idx = scipy.spatial.distance.cdist(lonlat,points).argmin(0) In [165]: np.column_stack((np.unravel_index(idx,lon.shape))).tolist() Out[165]: [[0, 4], [0, 4], [0, 4], [0, 4], [0, 4], [0, 4], [3, 3]]
Runtime Tests -
Define functions:
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 def loopy_app(lon,lat,pts): return [find_indices(lon,lat,pts[i,0],pts[i,1]) for i in range(pts.shape[0])] def vectorized_app(lon,lat,points): lonlat = np.column_stack((lon.ravel(),lat.ravel())) idx = scipy.spatial.distance.cdist(lonlat,points).argmin(0) return np.column_stack((np.unravel_index(idx,lon.shape))).tolist()
Timings:
In [179]: lon = np.random.rand(100,100) In [180]: lat = np.random.rand(100,100) In [181]: points = np.random.rand(50,2) In [182]: %timeit loopy_app(lon,lat,points) 10 loops, best of 3: 47 ms per loop In [183]: %timeit vectorized_app(lon,lat,points) 10 loops, best of 3: 16.6 ms per loop
To extrude more performance, np.concatenate can be used instead of np.column_stack .