Xarray clip or mask dataset with another dataset

Question:

Goal: Replace values of a dataset by NaNs if the values of another, smaller dataset, are non-nan.

Context: I have 1 netcdf file (DEM) that covers a large area. I have another netcdf file (BED) that covers a smaller area included in the bigger dataset. I would like to set to NaN every value of the DEM dataset overlapping with the BED dataset. How can I do that ?

Question: Is there an xarray function that can mask a dataset based on the values of another dataset, with different size ?

Lead: I thought of gathering the indices for which x and y in one dataset are simultaneously equal to x and y in the other dataset, but couldn’t manage to make it work because x and y of each dataset are never completely equal (just really close).

Dataset:

BED
Out[56]: 
<xarray.DataArray 'band_data' (band: 1, y: 370, x: 1000)>
array([[[nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        ...,
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan]]])
Coordinates:
  * x            (x) float64 -141.3 -141.3 -141.3 ... -139.9 -139.9 -139.9
  * y            (y) float64 60.18 60.18 60.18 60.17 ... 59.65 59.65 59.65 59.65
  * band         (band) int32 1
    spatial_ref  int32 0


DEM
Out[58]: 
<xarray.Dataset>
Dimensions:      (band: 1, x: 10800, y: 7200)
Coordinates:
  * band         (band) int32 1
  * x            (x) float64 -142.0 -142.0 -142.0 ... -139.0 -139.0 -139.0
  * y            (y) float64 61.0 61.0 61.0 61.0 61.0 ... 59.0 59.0 59.0 59.0
    spatial_ref  int32 ...
Data variables:
    band_data    (band, y, x) float32 1.79e+03 1.79e+03 1.796e+03 ... nan nan

Image:
BED (blue) is overlapping with DEM (yellow and dark blue/purple). I would like to turn all the yellow below BED to NaNs.
DEM with overlying BED

Asked By: Nihilum

||

Answers:

You can index a DataArray for assignment using a dictionary with .loc, then mask the matched values with .where:

DEM.loc[{"band": BED.band.values, "x": BED.x.values, "y": BED.y.values}] = (
    DEM.loc[{"band": BED.band.values, "x": BED.x.values, "y": BED.y.values}]
    .where(BED.isnull(), np.nan)
)

See the xarray guide to indexing and selecting data

Answered By: Michael Delgado
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.