Skip to content

Commit b53fa14

Browse files
authored
BUG: Fix MultiIndex column stacking with dupe names (#36371)
1 parent 0bfede2 commit b53fa14

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
@@ -29,6 +29,7 @@ Bug fixes
2929
- Bug in :func:`read_spss` where passing a ``pathlib.Path`` as ``path`` would raise a ``TypeError`` (:issue:`33666`)
3030
- Bug in :meth:`Series.str.startswith` and :meth:`Series.str.endswith` with ``category`` dtype not propagating ``na`` parameter (:issue:`36241`)
3131
- Bug in :class:`Series` constructor where integer overflow would occur for sufficiently large scalar inputs when an index was provided (:issue:`36291`)
32+
- Bug in :meth:`DataFrame.stack` raising a ``ValueError`` when stacking :class:`MultiIndex` columns based on position when the levels had duplicate names (:issue:`36353`)
3233

3334
.. ---------------------------------------------------------------------------
3435

pandas/core/reshape/reshape.py

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

603599
this = frame.copy()
604600

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)