Skip to content

Commit b1ff291

Browse files
dsm054jreback
authored andcommitted
BUG: Preserve data order when stacking unsorted levels (pandas-dev#16323) (pandas-dev#16325)
1 parent 0607e03 commit b1ff291

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

doc/source/whatsnew/v0.20.2.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Sparse
7373
Reshaping
7474
^^^^^^^^^
7575

76-
76+
- Bug in ``DataFrame.stack`` with unsorted levels in MultiIndex columns (:issue:`16323`)
7777

7878

7979
Numeric

pandas/core/reshape/reshape.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ def _convert_level_number(level_num, columns):
689689
new_labels = [np.arange(N).repeat(levsize)]
690690
new_names = [this.index.name] # something better?
691691

692-
new_levels.append(frame.columns.levels[level_num])
692+
new_levels.append(level_vals)
693693
new_labels.append(np.tile(level_labels, N))
694694
new_names.append(frame.columns.names[level_num])
695695

pandas/tests/test_multilevel.py

+31
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,37 @@ def test_unstack_unobserved_keys(self):
11931193
recons = result.stack()
11941194
tm.assert_frame_equal(recons, df)
11951195

1196+
def test_stack_order_with_unsorted_levels(self):
1197+
# GH 16323
1198+
1199+
def manual_compare_stacked(df, df_stacked, lev0, lev1):
1200+
assert all(df.loc[row, col] ==
1201+
df_stacked.loc[(row, col[lev0]), col[lev1]]
1202+
for row in df.index for col in df.columns)
1203+
1204+
# deep check for 1-row case
1205+
for width in [2, 3]:
1206+
levels_poss = itertools.product(
1207+
itertools.permutations([0, 1, 2], width),
1208+
repeat=2)
1209+
1210+
for levels in levels_poss:
1211+
columns = MultiIndex(levels=levels,
1212+
labels=[[0, 0, 1, 1],
1213+
[0, 1, 0, 1]])
1214+
df = DataFrame(columns=columns, data=[range(4)])
1215+
for stack_lev in range(2):
1216+
df_stacked = df.stack(stack_lev)
1217+
manual_compare_stacked(df, df_stacked,
1218+
stack_lev, 1 - stack_lev)
1219+
1220+
# check multi-row case
1221+
mi = MultiIndex(levels=[["A", "C", "B"], ["B", "A", "C"]],
1222+
labels=[np.repeat(range(3), 3), np.tile(range(3), 3)])
1223+
df = DataFrame(columns=mi, index=range(5),
1224+
data=np.arange(5 * len(mi)).reshape(5, -1))
1225+
manual_compare_stacked(df, df.stack(0), 0, 1)
1226+
11961227
def test_groupby_corner(self):
11971228
midx = MultiIndex(levels=[['foo'], ['bar'], ['baz']],
11981229
labels=[[0], [0], [0]],

0 commit comments

Comments
 (0)