Skip to content

Conversation

@ianhi
Copy link
Contributor

@ianhi ianhi commented Jan 28, 2026

  • Fixed the behavior of RangeIndex not being inclusive of the end of the slice (the pandas behavior)
  • Allow method=None for RangeIndex slices, and for TransformIndex single point selection.

For the latter I had to play some small tricks using eps to account for floating point error. I think this is the least invasive way to account for the case mentioned in the comments (0.7 - 0.1) / 0.1 = 5.999999999999999 instead of 6.0

Examples:

import numpy as np
import xarray as xr
from xarray.indexes import RangeIndex

# Create a dataset with RangeIndex
index = RangeIndex.arange(0.0, 1.0, 0.1, dim='x')
ds = xr.Dataset(coords=xr.Coordinates.from_xindex(index))

# Slice selection with method="nearest" (rounds to nearest positions)
print(ds.sel(x=slice(0.12, 0.28), method="nearest"))
# Returns x=[0.1, 0.2, 0.3] - inclusive on both ends
print('\n\n----\n\n')
# Slice selection with method=None (exact matching with ceil/floor)
print(ds.sel(x=slice(0.15, 0.65)))
# Returns x=[0.2, 0.3, 0.4, 0.5, 0.6] 

print('\n\n----\n\n')
# Point selection now works without method for exact values
print(ds.sel(x=0.2))
# Returns x=0.2
<xarray.Dataset> Size: 24B
Dimensions:  (x: 3)
Coordinates:
  * x        (x) float64 24B 0.1 0.2 0.3
Data variables:
    *empty*
Indexes:
    x        RangeIndex (start=0.1, stop=0.4, step=0.1)


----


<xarray.Dataset> Size: 40B
Dimensions:  (x: 5)
Coordinates:
  * x        (x) float64 40B 0.2 0.3 0.4 0.5 0.6
Data variables:
    *empty*
Indexes:
    x        RangeIndex (start=0.2, stop=0.7, step=0.1)


----


<xarray.Dataset> Size: 8B
Dimensions:  ()
Coordinates:
    x        float64 8B 0.2
Data variables:
    *empty*

also passes @dcherian request in #10533 (comment) of equivalency to PandasIndex slicing

import numpy as np
import pandas as pd
from xarray.indexes import RangeIndex, PandasIndex

range_idx = RangeIndex.arange(20, dim='x')
pandas_idx = PandasIndex(pd.Index(np.arange(20)), dim='x')

range_result = range_idx.sel({'x': slice(4, 8)}).dim_indexers['x']
pandas_result = pandas_idx.sel({'x': slice(4, 8)}).dim_indexers['x']

assert range_result == pandas_result  # Both return slice(4, 9, None)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support label-based slicing in RangeIndex

1 participant