How to calculate the euclidian distance between a specified coordinate and 2-d xarray data at once (without for loop)?
I wrote the following code. But if the data-size become larger, this script appears to be slow. How can I do the same thing without for loop ?
import math import xarray as xr import numpy as np #set the specified lat, lon specific_lat = 15 specific_lon = 65 #create sample xarry data lat = [0, 10, 20] lon = [50, 60, 70, 80] #sample data test_data = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]]) #to xarray data_xarray = xr.DataArray(test_data, dims=("lat","lon"), coords={"lat":lat, "lon":lon}) #calculate distance xarray_distance = data_xarray #copy xarray_distance.data[:,:] = 0.0 #zero-reset for lat in data_xarray.lat.data: for lon in data_xarray.lon.data: xarray_distance.loc[{"lat":lat,"lon":lon}] = math.sqrt((lat- spec_lat)**2 + (lon - spec_lon)**2) print(xarray_distance) #<xarray.DataArray (lat: 3, lon: 4)> #array([[21, 15, 15, 21], # [15, 7, 7, 15], # [15, 7, 7, 15]]) #Coordinates: # * lat (lat) int64 0 10 20 # * lon (lon) int64 50 60 70 80
Advertisement
Answer
First things first, xarray_distance = data_xarray
does not copy the object. Both names will see the same object and any changes that occur to it equally. For a copy, you want to do data_xarray.copy()
.
Now, instead of using loops, you want to take advantage of numpy’s vectorisation and broadcasting to create the 2D array in one go and set that to your xarray’s object data.
lat = np.array(lat) lon = np.array(lon) xarray_distance.data = np.sqrt((lat - spec_lat)[:,None]**2 + ((lon - spec_lon)**2))
Result
<xarray.DataArray (lat: 3, lon: 4)> array([[21.21320344, 15.8113883 , 15.8113883 , 21.21320344], [15.8113883 , 7.07106781, 7.07106781, 15.8113883 ], [15.8113883 , 7.07106781, 7.07106781, 15.8113883 ]]) Coordinates: * lat (lat) int32 0 10 20 * lon (lon) int32 50 60 70 80
You’ll notice the data are floats, as they should probably be, considering what they represent. If you want them in the original type of the data, substitute
xarray_distance.data = np.sqrt(...)
with
xarray_distance.data = np.sqrt(...).astype(xarray_distance.data.dtype)