Skip to content

Commit c85679c

Browse files
Backport PR #54885 on branch 2.1.x (REGR: setitem with part of a MultiIndex raises) (#54899)
Backport PR #54885: REGR: setitem with part of a MultiIndex raises Co-authored-by: Luke Manley <[email protected]>
1 parent 9dc8da8 commit c85679c

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

doc/source/whatsnew/v2.1.1.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ including other versions of pandas.
1313

1414
Fixed regressions
1515
~~~~~~~~~~~~~~~~~
16-
-
16+
- Fixed regression in :meth:`DataFrame.__setitem__` raising ``AssertionError`` when setting a :class:`Series` with a partial :class:`MultiIndex` (:issue:`54875`)
1717

1818
.. ---------------------------------------------------------------------------
1919
.. _whatsnew_211.bug_fixes:

pandas/core/indexes/multi.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2460,12 +2460,12 @@ def _reorder_ilevels(self, order) -> MultiIndex:
24602460
def _recode_for_new_levels(
24612461
self, new_levels, copy: bool = True
24622462
) -> Generator[np.ndarray, None, None]:
2463-
if len(new_levels) != self.nlevels:
2463+
if len(new_levels) > self.nlevels:
24642464
raise AssertionError(
24652465
f"Length of new_levels ({len(new_levels)}) "
2466-
f"must be same as self.nlevels ({self.nlevels})"
2466+
f"must be <= self.nlevels ({self.nlevels})"
24672467
)
2468-
for i in range(self.nlevels):
2468+
for i in range(len(new_levels)):
24692469
yield recode_for_categories(
24702470
self.codes[i], self.levels[i], new_levels[i], copy=copy
24712471
)

pandas/tests/indexing/multiindex/test_setitem.py

+18
Original file line numberDiff line numberDiff line change
@@ -556,3 +556,21 @@ def test_frame_setitem_copy_no_write(
556556

557557
result = df
558558
tm.assert_frame_equal(result, expected)
559+
560+
561+
def test_frame_setitem_partial_multiindex():
562+
# GH 54875
563+
df = DataFrame(
564+
{
565+
"a": [1, 2, 3],
566+
"b": [3, 4, 5],
567+
"c": 6,
568+
"d": 7,
569+
}
570+
).set_index(["a", "b", "c"])
571+
ser = Series(8, index=df.index.droplevel("c"))
572+
result = df.copy()
573+
result["d"] = ser
574+
expected = df.copy()
575+
expected["d"] = 8
576+
tm.assert_frame_equal(result, expected)

0 commit comments

Comments
 (0)