透视表在一定程度上可以称作是split-apply-combine
的快捷方式。DataFrame
有pivot_table()
方法,对应的顶级的pandas.pivot_table()
函数。除了提供便利的groupby
之外还提供了分项小计margins
。
import numpy as np
import pandas as pd
file = r'../data/tips.csv'
tips = pd.read_csv(file)
tips.head()
| total_bill | tip | smoker | day | time | size |
---|
0 | 16.99 | 1.01 | No | Sun | Dinner | 2 |
---|
1 | 10.34 | 1.66 | No | Sun | Dinner | 3 |
---|
2 | 21.01 | 3.50 | No | Sun | Dinner | 3 |
---|
3 | 23.68 | 3.31 | No | Sun | Dinner | 2 |
---|
4 | 24.59 | 3.61 | No | Sun | Dinner | 4 |
---|
tips['tip_pct'] = tips['tip'] / tips['tip'].sum()
tips.head()
| total_bill | tip | smoker | day | time | size | tip_pct |
---|
0 | 16.99 | 1.01 | No | Sun | Dinner | 2 | 0.001381 |
---|
1 | 10.34 | 1.66 | No | Sun | Dinner | 3 | 0.002269 |
---|
2 | 21.01 | 3.50 | No | Sun | Dinner | 3 | 0.004784 |
---|
3 | 23.68 | 3.31 | No | Sun | Dinner | 2 | 0.004524 |
---|
4 | 24.59 | 3.61 | No | Sun | Dinner | 4 | 0.004935 |
---|
便捷的分组平均
- 假设根据tips数据集,对time和smoker进行分组平均:
tips.pivot_table(index=['time', 'smoker'])
| | size | tip | tip_pct | total_bill |
---|
time | smoker | | | | |
---|
Dinner | No | 2.735849 | 3.126887 | 0.004274 | 20.095660 |
---|
Yes | 2.471429 | 3.066000 | 0.004191 | 21.859429 |
---|
Lunch | No | 2.511111 | 2.673778 | 0.003655 | 17.050889 |
---|
Yes | 2.217391 | 2.834348 | 0.003874 | 17.399130 |
---|
注意:所有的非数值类型被自动过滤,且默认聚合方法为平均值方法。
指定行列及聚合对象
- 假设我们对tip_pct, size进行聚合,将smoker作用在列上,将time, day作用在行上:
tips.pivot_table(columns='smoker', index=['time', 'day'], values=['tip_pct', 'size'])
| | size | tip_pct |
---|
| smoker | No | Yes | No | Yes |
---|
time | day | | | | |
---|
Dinner | Fri | 2.000000 | 2.222222 | 0.003759 | 0.004105 |
---|
Sat | 2.555556 | 2.476190 | 0.004241 | 0.003931 |
---|
Sun | 2.929825 | 2.578947 | 0.004330 | 0.004807 |
---|
Thur | 2.000000 | NaN | 0.004101 | NaN |
---|
Lunch | Fri | 3.000000 | 1.833333 | 0.004101 | 0.003117 |
---|
Thur | 2.500000 | 2.352941 | 0.003645 | 0.004142 |
---|
分项小计
- 在聚合后的基础上添加margins=True可以实现分项小计:
小计的结果使用All标记,同时列的复合索引根据最高级求和。
tips.pivot_table(columns='smoker', index=['time', 'day'], values=['tip_pct', 'size'], margins=True)
| | size | tip_pct |
---|
| smoker | No | Yes | All | No | Yes | All |
---|
time | day | | | | | | |
---|
Dinner | Fri | 2.000000 | 2.222222 | 2.166667 | 0.003759 | 0.004105 | 0.004019 |
---|
Sat | 2.555556 | 2.476190 | 2.517241 | 0.004241 | 0.003931 | 0.004091 |
---|
Sun | 2.929825 | 2.578947 | 2.842105 | 0.004330 | 0.004807 | 0.004449 |
---|
Thur | 2.000000 | NaN | 2.000000 | 0.004101 | NaN | 0.004101 |
---|
Lunch | Fri | 3.000000 | 1.833333 | 2.000000 | 0.004101 | 0.003117 | 0.003257 |
---|
Thur | 2.500000 | 2.352941 | 2.459016 | 0.003645 | 0.004142 | 0.003783 |
---|
All | | 2.668874 | 2.408602 | 2.569672 | 0.004090 | 0.004113 | 0.004098 |
---|
自定义聚合方法
- 默认方法是平均值
- 其他聚合方法可通过aggfunc来传递
tips.pivot_table(values='tip_pct', index=['time', 'smoker'], columns='day', aggfunc=len, margins=True, fill_value=0)
| day | Fri | Sat | Sun | Thur | All |
---|
time | smoker | | | | | |
---|
Dinner | No | 3 | 45 | 57 | 1 | 106.0 |
---|
Yes | 9 | 42 | 19 | 0 | 70.0 |
---|
Lunch | No | 1 | 0 | 0 | 44 | 45.0 |
---|
Yes | 6 | 0 | 0 | 17 | 23.0 |
---|
All | | 19 | 87 | 76 | 62 | 244.0 |
---|
复杂的聚合
tips.pivot_table(values=['size', 'tip_pct'], index=['time', 'smoker'], columns='day',
aggfunc={'tip_pct': [len, sum], 'size': max}, fill_value=0)
| | size | tip_pct |
---|
| | max | len | sum |
---|
| day | Fri | Sat | Sun | Thur | Fri | Sat | Sun | Thur | Fri | Sat | Sun | Thur |
---|
time | smoker | | | | | | | | | | | | |
---|
Dinner | No | 2 | 4 | 6 | 2 | 3 | 45 | 57 | 1 | 0.011277 | 0.190861 | 0.246822 | 0.004101 |
---|
Yes | 4 | 5 | 5 | 0 | 9 | 42 | 19 | 0 | 0.036947 | 0.165081 | 0.091337 | 0.000000 |
---|
Lunch | No | 3 | 0 | 0 | 6 | 1 | 0 | 0 | 44 | 0.004101 | 0.000000 | 0.000000 | 0.160365 |
---|
Yes | 2 | 0 | 0 | 4 | 6 | 0 | 0 | 17 | 0.018699 | 0.000000 | 0.000000 | 0.070409 |
---|
👉pivot_table()参数说明表:
参数名 | 说明 |
---|
values | 待聚合的列的名称,默认所有数值列。 |
index | 用于分组的列名或其他分组键,出现在结果透视表的行。 |
columns | 用于分组的列名或其他分组键,出现在结果透视表的列。 |
aggfunc | 聚合函数或函数列表,默认为mean。可以是对任何groupby有作用的函数。 |
fill_value | 用于替换结果中的空值的值 |
margins | 添加行列的小计 |