-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Support .sel
with method
kwarg for slices
#10711
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 13 commits
63c1b6a
c03b0e9
e65b759
20a6d3b
ee1da65
308d8c9
61c1412
d7ec746
8842b23
1fe2961
bb36ae7
4dd2d63
ae391b3
f10a3a2
74f3d07
d05ab1a
199765e
8cce331
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -560,23 +560,39 @@ def _sanitize_slice_element(x): | |
|
||
|
||
def _query_slice(index, label, coord_name="", method=None, tolerance=None): | ||
slice_label_start = _sanitize_slice_element(label.start) | ||
slice_label_stop = _sanitize_slice_element(label.stop) | ||
slice_index_step = _sanitize_slice_element(label.step) | ||
|
||
if method is not None or tolerance is not None: | ||
raise NotImplementedError( | ||
"cannot use ``method`` argument if any indexers are slice objects" | ||
# likely slower because it requires two lookups, but pandas.Index.slice_indexer doesn't support method or tolerance | ||
# see https://github.com/pydata/xarray/issues/10710 | ||
slice_index_start = index.get_indexer( | ||
[slice_label_start], method=method, tolerance=tolerance | ||
) | ||
indexer = index.slice_indexer( | ||
_sanitize_slice_element(label.start), | ||
_sanitize_slice_element(label.stop), | ||
_sanitize_slice_element(label.step), | ||
) | ||
if not isinstance(indexer, slice): | ||
# unlike pandas, in xarray we never want to silently convert a | ||
# slice indexer into an array indexer | ||
raise KeyError( | ||
"cannot represent labeled-based slice indexer for coordinate " | ||
f"{coord_name!r} with a slice over integer positions; the index is " | ||
"unsorted or non-unique" | ||
slice_index_stop = index.get_indexer( | ||
[slice_label_stop], method=method, tolerance=tolerance | ||
) | ||
|
||
# +1 needed to emulate behaviour of xarray sel with slice without method kwarg, which is inclusive of point at stop label | ||
|
||
indexer = slice( | ||
slice_index_start.item(), slice_index_stop.item() + 1, slice_index_step | ||
) | ||
else: | ||
indexer = index.slice_indexer( | ||
slice_label_start, | ||
slice_label_stop, | ||
slice_index_step, | ||
) | ||
if not isinstance(indexer, slice): | ||
# unlike pandas, in xarray we never want to silently convert a | ||
# slice indexer into an array indexer | ||
raise KeyError( | ||
"cannot represent labeled-based slice indexer for coordinate " | ||
f"{coord_name!r} with a slice over integer positions; the index is " | ||
"unsorted or non-unique" | ||
) | ||
|
||
return indexer | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2164,8 +2164,13 @@ def test_sel_method(self) -> None: | |
actual = data.sel(dim2=[1.45], method="backfill") | ||
assert_identical(expected, actual) | ||
|
||
with pytest.raises(NotImplementedError, match=r"slice objects"): | ||
data.sel(dim2=slice(1, 3), method="ffill") | ||
expected = data.isel(dim2=slice(2, 7)) | ||
actual = data.sel(dim2=slice(1, 3), method="ffill") | ||
assert_identical(expected, actual) | ||
|
||
expected = data.isel(dim2=slice(2, 7, 2)) | ||
actual = data.sel(dim2=slice(1, 3, 2), method="ffill") | ||
assert_identical(expected, actual) | ||
Comment on lines
+2167
to
+2173
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a test for |
||
|
||
with pytest.raises(TypeError, match=r"``method``"): | ||
# this should not pass silently | ||
|
@@ -2175,6 +2180,66 @@ def test_sel_method(self) -> None: | |
with pytest.raises(ValueError, match=r"cannot supply"): | ||
data.sel(dim1=0, method="nearest") | ||
|
||
def test_sel_method_with_slice(self) -> None: | ||
# regression test for https://github.com/pydata/xarray/issues/10710 | ||
|
||
data_int_coords = xr.Dataset(coords={"lat": ("lat", [20, 21, 22, 23])}) | ||
expected = xr.Dataset(coords={"lat": ("lat", [21, 22])}) | ||
actual = data_int_coords.sel(lat=slice(21, 22), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
# check non-zero step | ||
expected = xr.Dataset(coords={"lat": ("lat", [21])}) | ||
actual = data_int_coords.sel(lat=slice(21, 22, 2), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
# check consistency with not passing method kwarg, for case of ints, where method kwarg should be irrelevant | ||
expected = data_int_coords.sel(lat=slice(21, 22)) | ||
actual = data_int_coords.sel(lat=slice(21, 22), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
data_float_coords = xr.Dataset( | ||
coords={"lat": ("lat", [20.1, 21.1, 22.1, 23.1])} | ||
) | ||
expected = xr.Dataset(coords={"lat": ("lat", [21.1, 22.1])}) | ||
actual = data_float_coords.sel(lat=slice(21, 22), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
# check non-zero step | ||
expected = xr.Dataset(coords={"lat": ("lat", [21.1])}) | ||
actual = data_float_coords.sel(lat=slice(21, 22, 2), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
# backwards slices | ||
data_int_coords = xr.Dataset(coords={"lat": ("lat", [23, 22, 21, 20])}) | ||
expected = xr.Dataset(coords={"lat": ("lat", [22, 21])}) | ||
actual = data_int_coords.sel(lat=slice(22, 21), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
data_float_coords = xr.Dataset( | ||
coords={"lat": ("lat", [23.1, 22.1, 21.1, 20.1])} | ||
) | ||
expected = xr.Dataset(coords={"lat": ("lat", [22.1, 21.1])}) | ||
actual = data_float_coords.sel(lat=slice(22, 21), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
def test_sel_negative_slices(self) -> None: | ||
data_int_coords = xr.Dataset(coords={"lat": ("lat", [-23, -22, -21, -20])}) | ||
expected = xr.Dataset(coords={"lat": ("lat", [-22, -21])}) | ||
actual = data_int_coords.sel(lat=slice(-22, -21)) | ||
assert_identical(expected, actual) | ||
|
||
expected = xr.Dataset(coords={"lat": ("lat", [-22, -21])}) | ||
actual = data_int_coords.sel(lat=slice(-22, -21), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
data_float_coords = xr.Dataset( | ||
coords={"lat": ("lat", [-23.1, -22.1, -21.1, -20.1])} | ||
) | ||
expected = xr.Dataset(coords={"lat": ("lat", [-22.1, -21.1])}) | ||
actual = data_float_coords.sel(lat=slice(-22, -21), method="nearest") | ||
assert_identical(expected, actual) | ||
|
||
def test_loc(self) -> None: | ||
data = create_test_data() | ||
expected = data.sel(dim3="a") | ||
|
Uh oh!
There was an error while loading. Please reload this page.