# Handling slicing with circular longitude coordinates in xarray

**URL:** <https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608>\
**Category:** Visualization\
**Created:** [July 2, 2021, 3:23pm UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608 "2021-07-02T15:23:47Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![nwilliams6](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/nwilliams6/32/786_2.png) [@nwilliams6](https://discourse.pangeo.io/u/nwilliams6)\
**Post date:** [July 2, 2021, 3:23pm UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/1 "2021-07-02T15:23:47Z")

</div>

I’m working on dividing into basins (Pacific, Atlantic, Indian Southern Ocean) and taking some zonal averages in an xarray dataset. My longitude coordinates are currently 0:360E and so slicing the Atlantic is difficult because `lon=slice(298, 22)` does not make sense without xarray knowing that this is a circular axis. I know that I could switch the coordinates to -180:180E, but then slicing the Pacific becomes an issue.

I came across [this discussion of the xr.roll method](https://github.com/pydata/xarray/issues/624) which sounds like it might be a way forward, but am having trouble implementing it. I would prefer not to end up with duplicate datasets with different coordinates because I will be adding more derived variables throughout the analysis. Does anyone have an example they’d be willing to share? Thanks!

---

<div class="post-metadata">

**Author:** ![cisaacstern](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/cisaacstern/32/909_2.png) [@cisaacstern](https://discourse.pangeo.io/u/cisaacstern)\
**Post date:** [July 2, 2021, 4:48pm UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/2 "2021-07-02T16:48:09Z")

</div>

Noting that, as far as I understand it from @TomNicholas, the ongoing [Explicit Indexes Refactor](https://github.com/pydata/xarray/projects/1#card-48480198) of xarray aims to make circular indexing easier when complete. Unfortunately I don’t know how to accomplish it today. Tom, maybe you have a suggestion?

---

<div class="post-metadata">

**Author:** ![josephyang](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/josephyang/32/541_2.png) [@josephyang](https://discourse.pangeo.io/u/josephyang)\
**Post date:** [July 7, 2021, 3:39am UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/3 "2021-07-07T03:39:48Z")

</div>

What errors are you getting?

This is how I roll coordinates in my dataset (from 0-360 to -180-180) and haven’t had any issues yet. Without having to duplicate the dataset, perhaps this can be done once for the Atlantic and slice Pacific and Indian ocean separately?

```
    ds = ds.assign_coords(longitude=(((ds.longitude + 180) % 360) - 180))
    ds = ds.roll(longitude=int(len(ds['longitude']) / 2), roll_coords=True)
```

---

<div class="post-metadata">

**Author:** ![nwilliams6](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/nwilliams6/32/786_2.png) [@nwilliams6](https://discourse.pangeo.io/u/nwilliams6)\
**Post date:** [July 7, 2021, 4:37pm UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/4 "2021-07-07T16:37:41Z")

</div>

Thanks for the example code @josephyang ! That works really well, although it still means I have to have two datasets (or must roll and unroll each time I make a new plot). I’ll stay tuned for the update mentioned above.

---

<div class="post-metadata">

**Author:** ![mktippett](https://avatars.discourse-cdn.com/v4/letter/m/e9c0ed/32.png) [@mktippett](https://discourse.pangeo.io/u/mktippett)\
**Post date:** [July 8, 2021, 11:46am UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/5 "2021-07-08T11:46:48Z")

</div>

I’m curious does pangeo (or anybody other than the IRI DL) recognize and do the “right thing” with the _periodic_ longitude attribute? It’s pretty handy and seems like the right thing. (In annual cycle calculations the Jan-Dec month grid is periodic too)

grid: /X (degree\_east) periodic (0) to (2W) by 2.0 N= 180 pts :grid  
[http://iridl.ldeo.columbia.edu/SOURCES/.NOAA/.NCDC/.ERSST/.version5/.anom/](http://iridl.ldeo.columbia.edu/SOURCES/.NOAA/.NCDC/.ERSST/.version5/.anom/)

grid: /T (months since 01-Jan) periodic (Jan) to (Dec) by 1.0 N= 12 pts :grid  
[http://iridl.ldeo.columbia.edu/SOURCES/.NOAA/.NCDC/.ERSST/.version5/.anom/yearly-climatology/](http://iridl.ldeo.columbia.edu/SOURCES/.NOAA/.NCDC/.ERSST/.version5/.anom/yearly-climatology/)

---

<div class="post-metadata">

**Author:** ![nwilliams6](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/nwilliams6/32/786_2.png) [@nwilliams6](https://discourse.pangeo.io/u/nwilliams6)\
**Post date:** [August 6, 2021, 5:43pm UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/6 "2021-08-06T17:43:36Z")

</div>

@josephyang This worked well for me. But how would you go back the other direction? I now have some different datasets that are -180 to 180 but I need to get them to 0-360 so that I can slice across the longitudes 146-292E. Thanks!

---

<div class="post-metadata">

**Author:** ![rabernat](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/rabernat/32/22_2.png) [@rabernat](https://discourse.pangeo.io/u/rabernat)\
**Post date:** [August 6, 2021, 7:39pm UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/7 "2021-08-06T19:39:00Z")

</div>

FYI, this functionality will very soon be supported in xarray.

> <https://github.com/pydata/xarray/blob/main/design_notes/flexible_indexes_notes.md>

cc @benbovy

---

<div class="post-metadata">

**Author:** ![josephyang](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/josephyang/32/541_2.png) [@josephyang](https://discourse.pangeo.io/u/josephyang)\
**Post date:** [August 8, 2021, 7:14pm UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/8 "2021-08-08T19:14:06Z")

</div>

This should do it:

```auto
ds = ds.assign_coords(longitude=((360 + (ds.longitude % 360)) % 360))
ds = ds.roll(longitude=int(len(ds['longitude']) / 2),roll_coords=True)

```

---

<div class="post-metadata">

**Author:** ![benbovy](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/benbovy/32/592_2.png) [@benbovy](https://discourse.pangeo.io/u/benbovy)\
**Post date:** [August 8, 2021, 9:20pm UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/9 "2021-08-08T21:20:47Z")

</div>

Yes this looks like another great use case that the flexible indexes refactoring should make easier, e.g., via the implementation of some kind of `PeriodicBoundaryIndex` or via a more generic index with a `boundary='periodic'` option.

---

<div class="post-metadata">

**Author:** ![jdldeauna](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.pangeo.io/jdldeauna/32/1155_2.png) [@jdldeauna](https://discourse.pangeo.io/u/jdldeauna)\
**Post date:** [August 2, 2022, 4:51am UTC](https://discourse.pangeo.io/t/handling-slicing-with-circular-longitude-coordinates-in-xarray/1608/11 "2022-08-02T04:51:58Z")

</div>

Hi! This was a great thread on handling circular lon values, and I wonder if anyone had experience on doing this with curvilinear grids? I’m working with the `MPI-ESM1-2-LR` CMIP6 model and I’m trying to subset patches of the N Pacific ocean that are located at the edges of the lat/lon grid of this model:

```python
cat_url = "https://storage.googleapis.com/cmip6/pangeo-cmip6.json"
col = intake.open_esm_datastore(cat_url)
cat = col.search( table_id='Omon',experiment_id='historical',
             variable_id=['thetao'], grid_label='gn', member_id='r1i1p1f1',source_id='MPI-ESM1-2-LR') 
cmip6_compiled = cat.to_dataset_dict(
        zarr_kwargs={'consolidated':True, 'decode_times': True, 'use_cftime': True},
        aggregate=False)    
ds = xr.merge([v for k,v in cmip6_compiled.items()])
ds_subset = ds.where((ds.latitude > 0) & (ds.latitude < 60), drop=True).squeeze().load()
ds_subset['thetao'].isel(lev=0,time=0).plot(yincrease=False)

```

![0 to 60 N](https://canada1.discourse-cdn.com/flex030/uploads/pangeo/original/2X/5/5c3ee856f64c915ec0899ab4e989d954fd91ae2d.png)

```python
da = ds_subset.where((ds_subset.longitude > 125) & (ds_subset.longitude < 250), drop=True).squeeze().load()
da['thetao'].isel(lev=0,time=0).plot(yincrease=False)

```

![N Pacific](https://canada1.discourse-cdn.com/flex030/uploads/pangeo/original/2X/2/2786445ea9a77fa8d31f36273275873894075428.png)

I’ve used the `xr.roll` code mentioned above and it executes, however I get the ff error when I try to plot the resulting dataset:

```python
ValueError: The input coordinate is not sorted in increasing order along axis 0. This can lead to unexpected results. Consider calling the `sortby` method on the input DataArray. To plot data with categorical axes, consider using the `heatmap` function from the `seaborn` statistical plotting library.

```

I’ve tried looking over the [new functionality](https://github.com/pydata/xarray/projects/1) for handling these types of cases for `xarray` but I’m confused as to how to apply it to my dataset. I would appreciate any suggestions, thank you so much!
