diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 495dcc5700241..e67ec02737f57 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9196,7 +9196,14 @@ def truncate( raise ValueError(f"Truncate: {after} must be after {before}") slicer = [slice(None, None)] * self._AXIS_LEN - slicer[axis] = slice(before, after) + + # GH33756 + # Inverse before/after if ax is in decreasing order. + if ax.is_monotonic_increasing: + slicer[axis] = slice(before, after) + else: + slicer[axis] = slice(after, before) + result = self.loc[tuple(slicer)] if isinstance(ax, MultiIndex): diff --git a/pandas/tests/frame/methods/test_truncate.py b/pandas/tests/frame/methods/test_truncate.py index ad86ee1266874..65d50d1940b16 100644 --- a/pandas/tests/frame/methods/test_truncate.py +++ b/pandas/tests/frame/methods/test_truncate.py @@ -87,3 +87,45 @@ def test_truncate_nonsortedindex(self): msg = "truncate requires a sorted index" with pytest.raises(ValueError, match=msg): df.truncate(before=2, after=20, axis=1) + + def test_truncate_descendingorderindex(self): + # GH#33756 + + df = pd.DataFrame({"A": ["a", "b", "c", "d", "e"]}, index=[9, 6, 5, 4, 1]) + + start = 4 + end = 6 + + start_missing = 3 + end_missing = 7 + + # neither specified + truncated = df.truncate() + tm.assert_frame_equal(truncated, df) + + # start specified + expected = df[:4] + + truncated = df.truncate(before=start) + tm.assert_frame_equal(truncated, expected) + + truncated = df.truncate(before=start_missing) + tm.assert_frame_equal(truncated, expected) + + # end specified + expected = df[1:] + + truncated = df.truncate(after=end) + tm.assert_frame_equal(truncated, expected) + + truncated = df.truncate(after=end_missing) + tm.assert_frame_equal(truncated, expected) + + # both specified + expected = df[1:4] + + truncated = df.truncate(before=start, after=end) + tm.assert_frame_equal(truncated, expected) + + truncated = df.truncate(before=start_missing, after=end_missing) + tm.assert_frame_equal(truncated, expected)