diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 7a4f709e56104..177a38b526c6e 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -397,7 +397,7 @@ Missing MultiIndex ^^^^^^^^^^ -- +- :func:`DataFrame.loc` with ``axis=0`` and :class:`MultiIndex` when setting a value adds extra columns (:issue:`58116`) - I/O diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index c9b502add21e0..b3ae53272cae4 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -757,7 +757,7 @@ def _get_setitem_indexer(self, key): """ if self.name == "loc": # always holds here bc iloc overrides _get_setitem_indexer - self._ensure_listlike_indexer(key) + self._ensure_listlike_indexer(key, axis=self.axis) if isinstance(key, tuple): for x in key: @@ -857,8 +857,10 @@ def _ensure_listlike_indexer(self, key, axis=None, value=None) -> None: if isinstance(key, tuple) and len(key) > 1: # key may be a tuple if we are .loc # if length of key is > 1 set key to column part - key = key[column_axis] - axis = column_axis + # unless axis is already specified, then go with that + if axis is None: + axis = column_axis + key = key[axis] if ( axis == column_axis diff --git a/pandas/tests/indexing/multiindex/test_loc.py b/pandas/tests/indexing/multiindex/test_loc.py index 67b9ddebfb8bf..d482d20591a8a 100644 --- a/pandas/tests/indexing/multiindex/test_loc.py +++ b/pandas/tests/indexing/multiindex/test_loc.py @@ -381,6 +381,29 @@ def test_multiindex_setitem_columns_enlarging(self, indexer, exp_value): ) tm.assert_frame_equal(df, expected) + def test_multiindex_setitem_axis_set(self): + # GH#58116 + dates = pd.date_range("2001-01-01", freq="D", periods=2) + ids = ["i1", "i2", "i3"] + index = MultiIndex.from_product([dates, ids], names=["date", "identifier"]) + df = DataFrame(0.0, index=index, columns=["A", "B"]) + df.loc(axis=0)["2001-01-01", ["i1", "i3"]] = None + + expected = DataFrame( + [ + [None, None], + [0.0, 0.0], + [None, None], + [0.0, 0.0], + [0.0, 0.0], + [0.0, 0.0], + ], + index=index, + columns=["A", "B"], + ) + + tm.assert_frame_equal(df, expected) + def test_sorted_multiindex_after_union(self): # GH#44752 midx = MultiIndex.from_product(