Skip to content

Commit a1fa397

Browse files
authored
Fix using xarray's own times for slice indexing (#1998)
Fixes GH1240
1 parent 1d0fbe6 commit a1fa397

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

doc/whats-new.rst

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ Enhancements
4444
Bug fixes
4545
~~~~~~~~~
4646

47+
- Fixed labeled indexing with slice bounds given by xarray objects with
48+
datetime64 or timedelta64 dtypes (:issue:`1240`).
49+
By `Stephan Hoyer <https://github.com/shoyer>`_.
50+
4751
.. _whats-new.0.10.2:
4852

4953
v0.10.2 (13 March 2018)

xarray/core/indexing.py

+22-8
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,25 @@ def _expand_slice(slice_, size):
4848
return np.arange(*slice_.indices(size))
4949

5050

51-
def _try_get_item(x):
52-
try:
53-
return x.item()
54-
except AttributeError:
55-
return x
51+
def _sanitize_slice_element(x):
52+
from .variable import Variable
53+
from .dataarray import DataArray
54+
55+
if isinstance(x, (Variable, DataArray)):
56+
x = x.values
57+
58+
if isinstance(x, np.ndarray):
59+
if x.ndim != 0:
60+
raise ValueError('cannot use non-scalar arrays in a slice for '
61+
'xarray indexing: {}'.format(x))
62+
x = x[()]
63+
64+
if isinstance(x, np.timedelta64):
65+
# pandas does not support indexing with np.timedelta64 yet:
66+
# https://github.com/pandas-dev/pandas/issues/20393
67+
x = pd.Timedelta(x)
68+
69+
return x
5670

5771

5872
def _asarray_tuplesafe(values):
@@ -119,9 +133,9 @@ def convert_label_indexer(index, label, index_name='', method=None,
119133
raise NotImplementedError(
120134
'cannot use ``method`` argument if any indexers are '
121135
'slice objects')
122-
indexer = index.slice_indexer(_try_get_item(label.start),
123-
_try_get_item(label.stop),
124-
_try_get_item(label.step))
136+
indexer = index.slice_indexer(_sanitize_slice_element(label.start),
137+
_sanitize_slice_element(label.stop),
138+
_sanitize_slice_element(label.step))
125139
if not isinstance(indexer, slice):
126140
# unlike pandas, in xarray we never want to silently convert a
127141
# slice indexer into an array indexer

xarray/tests/test_dataarray.py

+16
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,22 @@ def test_sel_dataarray(self):
779779
assert 'new_dim' in actual.coords
780780
assert_equal(actual['new_dim'].drop('x'), ind['new_dim'])
781781

782+
def test_sel_invalid_slice(self):
783+
array = DataArray(np.arange(10), [('x', np.arange(10))])
784+
with raises_regex(ValueError, 'cannot use non-scalar arrays'):
785+
array.sel(x=slice(array.x))
786+
787+
def test_sel_dataarray_datetime(self):
788+
# regression test for GH1240
789+
times = pd.date_range('2000-01-01', freq='D', periods=365)
790+
array = DataArray(np.arange(365), [('time', times)])
791+
result = array.sel(time=slice(array.time[0], array.time[-1]))
792+
assert_equal(result, array)
793+
794+
array = DataArray(np.arange(365), [('delta', times - times[0])])
795+
result = array.sel(delta=slice(array.delta[0], array.delta[-1]))
796+
assert_equal(result, array)
797+
782798
def test_sel_no_index(self):
783799
array = DataArray(np.arange(10), dims='x')
784800
assert_identical(array[0], array.sel(x=0))

0 commit comments

Comments
 (0)