diff --git a/pandas/_testing/__init__.py b/pandas/_testing/__init__.py index c2c55a4060f7a..4f9ef2c3c3ffa 100644 --- a/pandas/_testing/__init__.py +++ b/pandas/_testing/__init__.py @@ -82,6 +82,7 @@ assert_extension_array_equal, assert_frame_equal, assert_index_equal, + assert_indexing_slices_equivalent, assert_interval_array_equal, assert_is_sorted, assert_is_valid_plot_return_object, diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index c9f7fd43c1050..82253b73a824f 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -1444,3 +1444,17 @@ def is_extension_array_dtype_and_needs_i8_conversion(left_dtype, right_dtype) -> Related to issue #37609 """ return is_extension_array_dtype(left_dtype) and needs_i8_conversion(right_dtype) + + +def assert_indexing_slices_equivalent(ser: Series, l_slc: slice, i_slc: slice): + """ + Check that ser.iloc[i_slc] matches ser.loc[l_slc] and, if applicable, + ser[l_slc]. + """ + expected = ser.iloc[i_slc] + + assert_series_equal(ser.loc[l_slc], expected) + + if not ser.index.is_integer(): + # For integer indices, .loc and plain getitem are position-based. + assert_series_equal(ser[l_slc], expected) diff --git a/pandas/tests/indexing/multiindex/test_slice.py b/pandas/tests/indexing/multiindex/test_slice.py index 42edaa2fe6c3a..55d45a21d643a 100644 --- a/pandas/tests/indexing/multiindex/test_slice.py +++ b/pandas/tests/indexing/multiindex/test_slice.py @@ -702,32 +702,30 @@ def test_per_axis_per_level_setitem(self): tm.assert_frame_equal(df, expected) def test_multiindex_label_slicing_with_negative_step(self): - s = Series( + ser = Series( np.arange(20), MultiIndex.from_product([list("abcde"), np.arange(4)]) ) SLC = pd.IndexSlice - def assert_slices_equivalent(l_slc, i_slc): - tm.assert_series_equal(s.loc[l_slc], s.iloc[i_slc]) - tm.assert_series_equal(s[l_slc], s.iloc[i_slc]) + tm.assert_indexing_slices_equivalent(ser, SLC[::-1], SLC[::-1]) - assert_slices_equivalent(SLC[::-1], SLC[::-1]) + tm.assert_indexing_slices_equivalent(ser, SLC["d"::-1], SLC[15::-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[("d",)::-1], SLC[15::-1]) - assert_slices_equivalent(SLC["d"::-1], SLC[15::-1]) - assert_slices_equivalent(SLC[("d",)::-1], SLC[15::-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[:"d":-1], SLC[:11:-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[:("d",):-1], SLC[:11:-1]) - assert_slices_equivalent(SLC[:"d":-1], SLC[:11:-1]) - assert_slices_equivalent(SLC[:("d",):-1], SLC[:11:-1]) + tm.assert_indexing_slices_equivalent(ser, SLC["d":"b":-1], SLC[15:3:-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[("d",):"b":-1], SLC[15:3:-1]) + tm.assert_indexing_slices_equivalent(ser, SLC["d":("b",):-1], SLC[15:3:-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[("d",):("b",):-1], SLC[15:3:-1]) + tm.assert_indexing_slices_equivalent(ser, SLC["b":"d":-1], SLC[:0]) - assert_slices_equivalent(SLC["d":"b":-1], SLC[15:3:-1]) - assert_slices_equivalent(SLC[("d",):"b":-1], SLC[15:3:-1]) - assert_slices_equivalent(SLC["d":("b",):-1], SLC[15:3:-1]) - assert_slices_equivalent(SLC[("d",):("b",):-1], SLC[15:3:-1]) - assert_slices_equivalent(SLC["b":"d":-1], SLC[:0]) - - assert_slices_equivalent(SLC[("c", 2)::-1], SLC[10::-1]) - assert_slices_equivalent(SLC[:("c", 2):-1], SLC[:9:-1]) - assert_slices_equivalent(SLC[("e", 0):("c", 2):-1], SLC[16:9:-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[("c", 2)::-1], SLC[10::-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[:("c", 2):-1], SLC[:9:-1]) + tm.assert_indexing_slices_equivalent( + ser, SLC[("e", 0):("c", 2):-1], SLC[16:9:-1] + ) def test_multiindex_slice_first_level(self): # GH 12697 diff --git a/pandas/tests/indexing/test_indexing.py b/pandas/tests/indexing/test_indexing.py index 7c7e9f79a77ae..2805c8877ed78 100644 --- a/pandas/tests/indexing/test_indexing.py +++ b/pandas/tests/indexing/test_indexing.py @@ -709,21 +709,17 @@ def run_tests(df, rhs, right_loc, right_iloc): def test_str_label_slicing_with_negative_step(self): SLC = pd.IndexSlice - def assert_slices_equivalent(l_slc, i_slc): - tm.assert_series_equal(s.loc[l_slc], s.iloc[i_slc]) - - if not idx.is_integer: - # For integer indices, .loc and plain getitem are position-based. - tm.assert_series_equal(s[l_slc], s.iloc[i_slc]) - tm.assert_series_equal(s.loc[l_slc], s.iloc[i_slc]) - for idx in [_mklbl("A", 20), np.arange(20) + 100, np.linspace(100, 150, 20)]: idx = Index(idx) - s = Series(np.arange(20), index=idx) - assert_slices_equivalent(SLC[idx[9] :: -1], SLC[9::-1]) - assert_slices_equivalent(SLC[: idx[9] : -1], SLC[:8:-1]) - assert_slices_equivalent(SLC[idx[13] : idx[9] : -1], SLC[13:8:-1]) - assert_slices_equivalent(SLC[idx[9] : idx[13] : -1], SLC[:0]) + ser = Series(np.arange(20), index=idx) + tm.assert_indexing_slices_equivalent(ser, SLC[idx[9] :: -1], SLC[9::-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[: idx[9] : -1], SLC[:8:-1]) + tm.assert_indexing_slices_equivalent( + ser, SLC[idx[13] : idx[9] : -1], SLC[13:8:-1] + ) + tm.assert_indexing_slices_equivalent( + ser, SLC[idx[9] : idx[13] : -1], SLC[:0] + ) def test_slice_with_zero_step_raises(self, indexer_sl, frame_or_series): obj = frame_or_series(np.arange(20), index=_mklbl("A", 20)) diff --git a/pandas/tests/series/indexing/test_indexing.py b/pandas/tests/series/indexing/test_indexing.py index 6c3587c7eeada..8a34882b1e5d4 100644 --- a/pandas/tests/series/indexing/test_indexing.py +++ b/pandas/tests/series/indexing/test_indexing.py @@ -338,26 +338,19 @@ def test_slice_with_zero_step_raises(index, frame_or_series, indexer_sli): ], ) def test_slice_with_negative_step(index): - def assert_slices_equivalent(l_slc, i_slc): - expected = ts.iloc[i_slc] - - tm.assert_series_equal(ts[l_slc], expected) - tm.assert_series_equal(ts.loc[l_slc], expected) - keystr1 = str(index[9]) keystr2 = str(index[13]) - box = type(index[0]) - ts = Series(np.arange(20), index) + ser = Series(np.arange(20), index) SLC = IndexSlice - for key in [keystr1, box(keystr1)]: - assert_slices_equivalent(SLC[key::-1], SLC[9::-1]) - assert_slices_equivalent(SLC[:key:-1], SLC[:8:-1]) + for key in [keystr1, index[9]]: + tm.assert_indexing_slices_equivalent(ser, SLC[key::-1], SLC[9::-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[:key:-1], SLC[:8:-1]) - for key2 in [keystr2, box(keystr2)]: - assert_slices_equivalent(SLC[key2:key:-1], SLC[13:8:-1]) - assert_slices_equivalent(SLC[key:key2:-1], SLC[0:0:-1]) + for key2 in [keystr2, index[13]]: + tm.assert_indexing_slices_equivalent(ser, SLC[key2:key:-1], SLC[13:8:-1]) + tm.assert_indexing_slices_equivalent(ser, SLC[key:key2:-1], SLC[0:0:-1]) def test_tuple_index():