Skip to content

Commit eecc0d1

Browse files
Backport PR #36371: BUG: Fix MultiIndex column stacking with dupe names (#36396)
Co-authored-by: Daniel Saxton <[email protected]>
1 parent 711f923 commit eecc0d1

File tree

3 files changed

+19
-9
lines changed

3 files changed

+19
-9
lines changed

doc/source/whatsnew/v1.1.3.rst

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Bug fixes
4545
- Bug in :func:`read_spss` where passing a ``pathlib.Path`` as ``path`` would raise a ``TypeError`` (:issue:`33666`)
4646
- Bug in :meth:`Series.str.startswith` and :meth:`Series.str.endswith` with ``category`` dtype not propagating ``na`` parameter (:issue:`36241`)
4747
- Bug in :class:`Series` constructor where integer overflow would occur for sufficiently large scalar inputs when an index was provided (:issue:`36291`)
48+
- Bug in :meth:`DataFrame.stack` raising a ``ValueError`` when stacking :class:`MultiIndex` columns based on position when the levels had duplicate names (:issue:`36353`)
4849

4950
.. ---------------------------------------------------------------------------
5051

pandas/core/reshape/reshape.py

+5-9
Original file line numberDiff line numberDiff line change
@@ -588,19 +588,15 @@ def _stack_multi_columns(frame, level_num=-1, dropna=True):
588588
def _convert_level_number(level_num, columns):
589589
"""
590590
Logic for converting the level number to something we can safely pass
591-
to swaplevel:
591+
to swaplevel.
592592
593-
We generally want to convert the level number into a level name, except
594-
when columns do not have names, in which case we must leave as a level
595-
number
593+
If `level_num` matches a column name return the name from
594+
position `level_num`, otherwise return `level_num`.
596595
"""
597596
if level_num in columns.names:
598597
return columns.names[level_num]
599-
else:
600-
if columns.names[level_num] is None:
601-
return level_num
602-
else:
603-
return columns.names[level_num]
598+
599+
return level_num
604600

605601
this = frame.copy()
606602

pandas/tests/frame/test_reshape.py

+13
Original file line numberDiff line numberDiff line change
@@ -1302,3 +1302,16 @@ def test_unstacking_multi_index_df():
13021302
),
13031303
)
13041304
tm.assert_frame_equal(result, expected)
1305+
1306+
1307+
def test_stack_positional_level_duplicate_column_names():
1308+
# https://github.com/pandas-dev/pandas/issues/36353
1309+
columns = pd.MultiIndex.from_product([("x", "y"), ("y", "z")], names=["a", "a"])
1310+
df = pd.DataFrame([[1, 1, 1, 1]], columns=columns)
1311+
result = df.stack(0)
1312+
1313+
new_columns = pd.Index(["y", "z"], name="a")
1314+
new_index = pd.MultiIndex.from_tuples([(0, "x"), (0, "y")], names=[None, "a"])
1315+
expected = pd.DataFrame([[1, 1], [1, 1]], index=new_index, columns=new_columns)
1316+
1317+
tm.assert_frame_equal(result, expected)

0 commit comments

Comments
 (0)