diff --git a/pandas/core/frame.py b/pandas/core/frame.py index cc260770cbd78..60f221666c188 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -4075,8 +4075,10 @@ def __getitem__(self, key): key = lib.item_from_zerodim(key) key = com.apply_if_callable(key, self) - if is_hashable(key) and not is_iterator(key): + if is_hashable(key) and not is_iterator(key) and not isinstance(key, slice): # is_iterator to exclude generator e.g. test_getitem_listlike + # As of Python 3.12, slice is hashable which breaks MultiIndex (GH#57500) + # shortcut if the key is in columns is_mi = isinstance(self.columns, MultiIndex) # GH#45316 Return view if key is not duplicated diff --git a/pandas/tests/frame/indexing/test_indexing.py b/pandas/tests/frame/indexing/test_indexing.py index 1388f41e6f7ee..1e270b2db7181 100644 --- a/pandas/tests/frame/indexing/test_indexing.py +++ b/pandas/tests/frame/indexing/test_indexing.py @@ -538,6 +538,16 @@ def test_loc_setitem_boolean_mask_allfalse(self): result.loc[result.b.isna(), "a"] = result.a.copy() tm.assert_frame_equal(result, df) + def test_getitem_slice_empty(self): + df = DataFrame([[1]], columns=MultiIndex.from_product([["A"], ["a"]])) + result = df[:] + + expected = DataFrame([[1]], columns=MultiIndex.from_product([["A"], ["a"]])) + + tm.assert_frame_equal(result, expected) + # Ensure df[:] returns a view of df, not the same object + assert result is not df + def test_getitem_fancy_slice_integers_step(self): df = DataFrame(np.random.default_rng(2).standard_normal((10, 5))) diff --git a/pandas/tests/frame/methods/test_join.py b/pandas/tests/frame/methods/test_join.py index 735f6c50ab739..9c8f42075343e 100644 --- a/pandas/tests/frame/methods/test_join.py +++ b/pandas/tests/frame/methods/test_join.py @@ -574,3 +574,41 @@ def test_frame_join_tzaware(self): tm.assert_index_equal(result.index, expected) assert result.index.tz.zone == "US/Central" + + def test_frame_join_categorical_index(self): + # GH 61675 + cat_data = pd.Categorical( + [15, 16, 17, 18], + categories=pd.Series(list(range(3, 24)), dtype="Int64"), + ordered=True, + ) + values1 = "a b c d".split() + values2 = "xyzzy foo bar ...".split() + df1 = DataFrame({"hr": cat_data, "values1": values1}).set_index("hr") + df2 = DataFrame({"hr": cat_data, "values2": values2}).set_index("hr") + df1.columns = pd.CategoricalIndex([4], dtype=cat_data.dtype, name="other_hr") + df2.columns = pd.CategoricalIndex([3], dtype=cat_data.dtype, name="other_hr") + + df_joined_1 = ( + df1.reset_index(level="hr") + .merge(df2.reset_index(level="hr"), on="hr") + .set_index("hr") + ) + expected1 = DataFrame( + {"hr": cat_data, "values1": values1, "values2": values2} + ).set_index("hr") + expected1.columns = Index([4, 3], dtype="object", name="other_hr") + + tm.assert_frame_equal(df_joined_1, expected1) + + df_joined_2 = df1.join(df2) + expected2 = DataFrame( + {"hr": cat_data, "values1": values1, "values2": values2} + ).set_index("hr") + expected2.columns = pd.CategoricalIndex( + [4, 3], dtype=cat_data.dtype, name="other_hr" + ) + + tm.assert_frame_equal(df_joined_2, expected2) + + assert df_joined_1.equals(df_joined_2)