Skip to content

Commit 02a7420

Browse files
authored
BUG: DataFrame.pivot drops column level names when both rows and columns are multiindexed (#36655)
1 parent f646ea0 commit 02a7420

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

doc/source/whatsnew/v1.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ Reshaping
525525
- Bug in func :meth:`crosstab` when using multiple columns with ``margins=True`` and ``normalize=True`` (:issue:`35144`)
526526
- Bug in :meth:`DataFrame.agg` with ``func={'name':<FUNC>}`` incorrectly raising ``TypeError`` when ``DataFrame.columns==['Name']`` (:issue:`36212`)
527527
- Bug in :meth:`Series.transform` would give incorrect results or raise when the argument ``func`` was dictionary (:issue:`35811`)
528+
- Bug in :meth:`DataFrame.pivot` did not preserve :class:`MultiIndex` level names for columns when rows and columns both multiindexed (:issue:`36360`)
528529
- Bug in :func:`join` returned a non deterministic level-order for the resulting :class:`MultiIndex` (:issue:`36910`)
529530
-
530531

pandas/core/groupby/generic.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1645,8 +1645,8 @@ def _wrap_aggregated_output(
16451645
DataFrame
16461646
"""
16471647
indexed_output = {key.position: val for key, val in output.items()}
1648-
name = self._obj_with_exclusions._get_axis(1 - self.axis).name
1649-
columns = Index([key.label for key in output], name=name)
1648+
columns = Index([key.label for key in output])
1649+
columns._set_names(self._obj_with_exclusions._get_axis(1 - self.axis).names)
16501650

16511651
result = self.obj._constructor(indexed_output)
16521652
result.columns = columns

pandas/tests/reshape/test_pivot_multilevel.py

+33-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import pytest
33

44
import pandas as pd
5-
from pandas import Index, MultiIndex
5+
from pandas import Index, Int64Index, MultiIndex
66
import pandas._testing as tm
77

88

@@ -190,3 +190,35 @@ def test_pivot_list_like_columns(
190190
expected_values, columns=expected_columns, index=expected_index
191191
)
192192
tm.assert_frame_equal(result, expected)
193+
194+
195+
def test_pivot_multiindexed_rows_and_cols():
196+
# GH 36360
197+
198+
df = pd.DataFrame(
199+
data=np.arange(12).reshape(4, 3),
200+
columns=MultiIndex.from_tuples(
201+
[(0, 0), (0, 1), (0, 2)], names=["col_L0", "col_L1"]
202+
),
203+
index=MultiIndex.from_tuples(
204+
[(0, 0, 0), (0, 0, 1), (1, 1, 1), (1, 0, 0)],
205+
names=["idx_L0", "idx_L1", "idx_L2"],
206+
),
207+
)
208+
209+
res = df.pivot_table(
210+
index=["idx_L0"],
211+
columns=["idx_L1"],
212+
values=[(0, 1)],
213+
aggfunc=lambda col: col.values.sum(),
214+
)
215+
216+
expected = pd.DataFrame(
217+
data=[[5.0, np.nan], [10.0, 7.0]],
218+
columns=MultiIndex.from_tuples(
219+
[(0, 1, 0), (0, 1, 1)], names=["col_L0", "col_L1", "idx_L1"]
220+
),
221+
index=Int64Index([0, 1], dtype="int64", name="idx_L0"),
222+
)
223+
224+
tm.assert_frame_equal(res, expected)

0 commit comments

Comments
 (0)