7

I'm just starting with using xarray for working with n-dimensional NetCDF datasets. I particularly like the techniques for slicing using both indexes and labels (isel and sel):

import xarray as xr
ds = xr.open_dataset('/path/to/data.nc', decode_times=False, chunks={'time': 1, 'depth': 1})
v = ds['my-variable'].isel(**{'time': 0, 'depth': 0}).sel(**{'lat': slice(-90,90,10), 'lon': slice(40,-80,5)})

This works great if my longitude slice is increasing (-80° to 40°), but not if I want the 'wrap' version of that, which crosses the antimeridian (40° to -80°), as in my snippet above. For example:

>>> v = ds['my-variable'].isel(**{'time': 0, 'depth': 0}).sel(**{'lat': slice(-90,90,10), 'lon': slice(40,-80,5)})
>>> v['lat'].shape
(0,)

Yet:

>>> v = ds['my-variable'].isel(**{'time': 0, 'depth': 0}).sel(**{'lat': slice(-90,90,10), 'lon': slice(-80,40,5)})
>>> v['lat'].shape
(1501,)

The only difference is 'lon': slice(-80,40,5) (returns data, but not the data I want) vs 'lon': slice(40,-80,5) (returns no data).

What is the best way to slice with longitude spanning the antimeridian with xarray?

4
  • Unlikely to work but do you get anything if you use 'lon': slice(40,280,5) ?
    – mkennedy
    Commented Aug 4, 2016 at 23:21
  • @mkennedy yes, but only 40°→179.9°, so only up to the antimeridian. Commented Aug 4, 2016 at 23:24
  • Well, it was a long shot.
    – mkennedy
    Commented Aug 4, 2016 at 23:25
  • Related question here : to change longitude from 0/360 to -180/180 stackoverflow.com/questions/53345442/…
    – Florian
    Commented Apr 5, 2019 at 12:43

1 Answer 1

12

Xarray is (intentionally) ignorant of coordinate systems, so it has no special handling for cyclic coordinates such as longitude. Because your longitude array has only increasing values, xarray interprets selections like slice(40, -80) in the same way that x[i:j] works if x is a NumPy array and i > j >= 0, and thus returns an empty selection.

The easiest way to work around this is to use boolean indexing instead:

ds.sel(lon=(ds.lon < -80) | (ds.lon > 40))

The inner parentheses are important, because | has higher operator precedence than < in Python.

Alternatively (maybe if you're studying the Pacific ocean), you might find it convenient to adjust the coordinate system of your data so it is centered over the anti-meridian instead. This is straightforward to accomplish with roll:

ds_rolled = ds.assign_coords(lon=(ds.lon % 360)).roll(lon=(ds.dims['lon'] // 2))
1
  • Thank you. I had got as far as rolling and shifting, but the Boolean indexing works great, and in particular keeps on behaving lazily. Commented Aug 6, 2016 at 0:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.