Pandas 如何透视表中更改列多级索引的分组方式
问题描述
假设我有一个如下所示的数据框:
data = {'City': ['Rochester', 'Anaheim', 'Toledo', 'Rochester', 'Anaheim', 'Anaheim', 'Toledo', 'Rochester', 'Rochester', 'Rochester', 'Toledo', 'Toledo', 'Toledo', 'Anaheim'],
'PersonID': [4930, 7343, 4368, 6909, 4574, 4086, 5024, 3642, 9997, 4745, 1207, 6081, 7832, 6309],
'MoneySpent': [100, 1710, 20, 910, 2040, 1100, 490, 70, 1940, 100, 1240, 80, 1420, 2090],
'StayDuration': ['< 2 days', '2-7 days', '2-7 days', '7-30 days', '7-30 days', '< 2 days', '2-7 days', '7-30 days', '7-30 days', '2-7 days', '7-30 days', '< 2 days', '< 2 days', '7-30 days']
}
df = pd.DataFrame(data)
City PersonID MoneySpent StayDuration
0 Rochester 4930 100 < 2 days
1 Anaheim 7343 1710 2-7 days
2 Toledo 4368 20 2-7 days
3 Rochester 6909 910 7-30 days
4 Anaheim 4574 2040 7-30 days
5 Anaheim 4086 1100 < 2 days
6 Toledo 5024 490 2-7 days
7 Rochester 3642 70 7-30 days
8 Rochester 9997 1940 7-30 days
9 Rochester 4745 100 2-7 days
10 Toledo 1207 1240 7-30 days
11 Toledo 6081 80 < 2 days
12 Toledo 7832 1420 < 2 days
13 Anaheim 6309 2090 7-30 days
然后,我将建立一个透视表,以显示每个城市的逗留时间的人数和总费用:
pv = pd.pivot_table(df,
index='City',
columns='StayDuration',
values=['PersonID', 'MoneySpent'],
aggfunc={'PersonID': 'count', 'MoneySpent': 'sum'}
)
我看到的是第一级别的指标(人数或支出),然后是其中的类别:
MoneySpent PersonID
StayDuration 2-7 days 7-30 days < 2 days 2-7 days 7-30 days < 2 days
City
Anaheim 1710 4130 1100 1 2 1
Rochester 100 2920 100 1 3 1
Toledo 510 1240 1500 2 1 2
我想要的是首先有分类,然后在其中包含指标,就像这样:
2-7 days 7-30 days < 2 days
PersonID MoneySpent PersonID MoneySpent PersonID MoneySpent
Anaheim 1 1710 2 4130 1 1100
Rochester 1 100 3 2920 1 100
Toledo 2 510 1 1240 2 1500
顺便说一下,这是Excel数据透视表的默认视图。
我花了令人惊讶的长时间才弄清楚如何让Python得到相同的结果。是否可以改变列的分组顺序?
解决方案
据我所知,pandas的数据透视表始终会以这种方式对列进行排序。您需要进行一些操作才能得到所需的输出结果:
pv.swaplevel(0,1,axis=1).sort_index(axis=1).reindex(['PersonID', 'MoneySpent'], level=1, axis=1)
输出:
StayDuration 2-7 days 7-30 days < 2 days
PersonID MoneySpent PersonID MoneySpent PersonID MoneySpent
City
Anaheim 1 1710 2 4130 1 1100
Rochester 1 100 3 2920 1 100
Toledo 2 510 1 1240 2 1500