diff --git a/doc/source/whatsnew/v0.19.0.txt b/doc/source/whatsnew/v0.19.0.txt index 454ffc5e5c685..d7f481d2a268b 100644 --- a/doc/source/whatsnew/v0.19.0.txt +++ b/doc/source/whatsnew/v0.19.0.txt @@ -1521,7 +1521,7 @@ Bug Fixes - Bug in ``.shift`` raises ``AmbiguousTimeError`` if data contains datetime near DST boundary (:issue:`13926`) - Bug in ``pd.read_hdf()`` returns incorrect result when a ``DataFrame`` with a ``categorical`` column and a query which doesn't match any values (:issue:`13792`) - Bug in ``.iloc`` when indexing with a non lex-sorted MultiIndex (:issue:`13797`) - +- Bug in ``.loc`` when indexing with date strings in a reverse sorted ``DatetimeIndex`` (:issue:`14316`) - Bug in ``Series`` comparison operators when dealing with zero dim NumPy arrays (:issue:`13006`) - Bug in ``.combine_first`` may return incorrect ``dtype`` (:issue:`7630`, :issue:`10567`) diff --git a/pandas/tests/indexing/test_indexing.py b/pandas/tests/indexing/test_indexing.py index e0d63d5aa0c44..fa406a27bef69 100644 --- a/pandas/tests/indexing/test_indexing.py +++ b/pandas/tests/indexing/test_indexing.py @@ -100,7 +100,7 @@ class TestIndexing(tm.TestCase): _multiprocess_can_split_ = True _objs = set(['series', 'frame', 'panel']) - _typs = set(['ints', 'labels', 'mixed', 'ts', 'floats', 'empty']) + _typs = set(['ints', 'labels', 'mixed', 'ts', 'floats', 'empty', 'ts_rev']) def setUp(self): @@ -137,6 +137,15 @@ def setUp(self): self.panel_ts = Panel(np.random.randn(4, 4, 4), items=date_range('20130101', periods=4)) + dates_rev = (date_range('20130101', periods=4) + .sort_values(ascending=False)) + self.series_ts_rev = Series(np.random.randn(4), + index=dates_rev) + self.frame_ts_rev = DataFrame(np.random.randn(4, 4), + index=dates_rev) + self.panel_ts_rev = Panel(np.random.randn(4, 4, 4), + items=dates_rev) + self.frame_empty = DataFrame({}) self.series_empty = Series({}) self.panel_empty = Panel({}) @@ -1358,6 +1367,10 @@ def test_loc_getitem_label_slice(self): 'ix', slice('20130102', '20130104'), typs=['ts'], axes=2, fails=TypeError) + # GH 14316 + self.check_result('ts slice rev', 'loc', slice('20130104', '20130102'), + 'indexer', [0, 1, 2], typs=['ts_rev'], axes=0) + self.check_result('mixed slice', 'loc', slice(2, 8), 'ix', slice(2, 8), typs=['mixed'], axes=0, fails=TypeError) self.check_result('mixed slice', 'loc', slice(2, 8), 'ix', slice(2, 8), diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py index b2326cb7b3255..ff6c0b85a1e5c 100644 --- a/pandas/tseries/index.py +++ b/pandas/tseries/index.py @@ -1446,8 +1446,14 @@ def _maybe_cast_slice_bound(self, label, side, kind): freq = getattr(self, 'freqstr', getattr(self, 'inferred_freq', None)) _, parsed, reso = parse_time_string(label, freq) - bounds = self._parsed_string_to_bounds(reso, parsed) - return bounds[0 if side == 'left' else 1] + lower, upper = self._parsed_string_to_bounds(reso, parsed) + # lower, upper form the half-open interval: + # [parsed, parsed + 1 freq) + # because label may be passed to searchsorted + # the bounds need swapped if index is reverse sorted + if self.is_monotonic_decreasing: + return upper if side == 'left' else lower + return lower if side == 'left' else upper else: return label