读书记录——pandas中的分组方法groupby(二)

续接读书记录——pandas中的分组方法groupby(一)。

6、逐级多列运用聚合函数

1)简单例子

#使用 小费数据集。进行测试
tips = pd.read_csv('/Users/daxu/vsCodePy/study_ws/pydata-book/examples/tips.csv')
# 增加维度属性,小费比例
tips['tip_pct'] = tips['tip'] / tips['total_bill']
#对 day 和 smoker 来进行分组
grouped = tips.groupby(['day', 'smoker'])
grouped_pct = grouped['tip_pct']
#如果传递的是函数或者函数名的列表,你会获得一个列名是这些函数名的DataFrame:
grouped_pct.agg(['std','mean',peak_to_peak])

	std	mean	peak_to_peak
day	smoker			
Fri	No	0.028123	0.151650	0.067349
Yes	0.051293	0.174783	0.159925
Sat	No	0.039767	0.158048	0.235193
Yes	0.061375	0.147906	0.290095
Sun	No	0.042347	0.160113	0.193226
Yes	0.154134	0.187250	0.644685
Thur	No	0.038774	0.160298	0.193350
Yes	0.039389	0.163863	0.151240

2)也可以给各个统计结果的列名重命名

grouped_pct.agg([('foo','std'),('foo1','mean'),('foo2',peak_to_peak)])
foo	foo1	foo2
day	smoker			
Fri	No	0.028123	0.151650	0.067349
Yes	0.051293	0.174783	0.159925
Sat	No	0.039767	0.158048	0.235193
Yes	0.061375	0.147906	0.290095
Sun	No	0.042347	0.160113	0.193226
Yes	0.154134	0.187250	0.644685
Thur	No	0.038774	0.160298	0.193350
Yes	0.039389	0.163863	0.151240

3)在多个列上面应用不同的函数

grouped_pct = grouped['tip_pct','total_bill']
#如果传递的是函数或者函数名的列表,你会获得一个列名是这些函数名的DataFrame:
result = grouped_pct.agg(['std','mean',peak_to_peak])
result

tip_pct	total_bill
std	mean	peak_to_peak	std	mean	peak_to_peak
day	smoker						
Fri	No	0.028123	0.151650	0.067349	5.059282	18.420000	10.29
Yes	0.051293	0.174783	0.159925	9.086388	16.813333	34.42
Sat	No	0.039767	0.158048	0.235193	8.939181	19.661778	41.08
Yes	0.061375	0.147906	0.290095	10.069138	21.276667	47.74
Sun	No	0.042347	0.160113	0.193226	8.130189	20.506667	39.40
Yes	0.154134	0.187250	0.644685	10.442511	24.120000	38.10
Thur	No	0.038774	0.160298	0.193350	7.721728	17.113111	33.68
Yes	0.039389	0.163863	0.151240	8.355149	19.190588	32.77

# 产生的DataFrame拥有分层列,与分别聚合每一列,再以列名作为keys参数使用concat将结果拼接在一起的结果相同:
result['tip_pct']

std	mean	peak_to_peak
day	smoker			
Fri	No	0.028123	0.151650	0.067349
Yes	0.051293	0.174783	0.159925
Sat	No	0.039767	0.158048	0.235193
Yes	0.061375	0.147906	0.290095
Sun	No	0.042347	0.160113	0.193226
Yes	0.154134	0.187250	0.644685
Thur	No	0.038774	0.160298	0.193350
Yes	0.039389	0.163863	0.151240

4)将不同的函数应用到一个或多个列上。要实现这个功能,需要将含有列名与函数对应关系的字典传递给agg:

grouped.agg({'tip': np.max, 'size':'sum'})
	tip	size
day	smoker		
Fri	No	3.50	9
Yes	4.73	31
Sat	No	9.00	115
Yes	10.00	104
Sun	No	6.00	167
Yes	6.50	49
Thur	No	6.70	112
Yes	5.00	40

result = grouped.agg({'tip_pct':['sum',np.max,'mean'],'size':'sum'})
result
tip_pct	size
sum	amax	mean	sum
day	smoker				
Fri	No	0.606602	0.187735	0.151650	9
Yes	2.621746	0.263480	0.174783	31
Sat	No	7.112145	0.291990	0.158048	115
Yes	6.212055	0.325733	0.147906	104
Sun	No	9.126438	0.252672	0.160113	167
Yes	3.557756	0.710345	0.187250	49
Thur	No	7.213414	0.266312	0.160298	112
Yes	2.785676	0.241255	0.163863	40

#只有多个函数应用于至少一个列时,DataFrame才具有分层列。
result['size']
	sum
day	smoker	
Fri	No	9
Yes	31
Sat	No	115
Yes	104
Sun	No	167
Yes	49
Thur	No	112
Yes	40

# 自动去掉了object类型的字段 ,并且 index模式是 分组列 ,不方便操作
index_group = tips.groupby(['day','smoker']).mean()
index_group

total_bill	tip	size	tip_pct
day	smoker				
Fri	No	18.420000	2.812500	2.250000	0.151650
Yes	16.813333	2.714000	2.066667	0.174783
Sat	No	19.661778	3.102889	2.555556	0.158048
Yes	21.276667	2.875476	2.476190	0.147906
Sun	No	20.506667	3.167895	2.929825	0.160113
Yes	24.120000	3.516842	2.578947	0.187250
Thur	No	17.113111	2.673778	2.488889	0.160298
Yes	19.190588	3.030000	2.352941	0.163863

4)不使用索引进行分组,调用reset_index()

index_group.reset_index()
day	smoker	total_bill	tip	size	tip_pct
0	Fri	No	18.420000	2.812500	2.250000	0.151650
1	Fri	Yes	16.813333	2.714000	2.066667	0.174783
2	Sat	No	19.661778	3.102889	2.555556	0.158048
3	Sat	Yes	21.276667	2.875476	2.476190	0.147906
4	Sun	No	20.506667	3.167895	2.929825	0.160113
5	Sun	Yes	24.120000	3.516842	2.578947	0.187250
6	Thur	No	17.113111	2.673778	2.488889	0.160298
7	Thur	Yes	19.190588	3.030000	2.352941	0.163863

大多数情况下可以通过向groupby传递as_index=False来禁用分组键作为索引的行为:

tips.groupby(['day','smoker'], as_index=False).mean()
day	smoker	total_bill	tip	size	tip_pct
0	Fri	No	18.420000	2.812500	2.250000	0.151650
1	Fri	Yes	16.813333	2.714000	2.066667	0.174783
2	Sat	No	19.661778	3.102889	2.555556	0.158048
3	Sat	Yes	21.276667	2.875476	2.476190	0.147906
4	Sun	No	20.506667	3.167895	2.929825	0.160113
5	Sun	Yes	24.120000	3.516842	2.578947	0.187250
6	Thur	No	17.113111	2.673778	2.488889	0.160298
7	Thur	Yes	19.190588	3.030000	2.352941	0.163863
7、应用: 通用拆分-应用-联合 groupby的 apply应用

1)简单例子

def top(df, n=5, column='tip_pct'):
    return df.sort_values(by=column)[:n]
top(tips)
total_bill	tip	smoker	day	time	size	tip_pct
237	32.83	1.17	Yes	Sat	Dinner	2	0.035638
102	44.30	2.50	Yes	Sat	Dinner	3	0.056433
57	26.41	1.50	No	Sat	Dinner	2	0.056797
0	16.99	1.01	No	Sun	Dinner	2	0.059447
187	30.46	2.00	Yes	Sun	Dinner	5	0.065660

#我们使用groupby 分组,还可以得到每个组的 结果:
#这里发生了什么?top函数在DataFrame的每一行分组上被调用,之后使用pandas. concat将函数结果粘贴在一起,并使用分组名作为各组的标签。因此结果包含一个分层索引,该分层索引的内部层级包含原DataFrame的索引值

tips.groupby(['smoker']).apply(top)
total_bill	tip	smoker	day	time	size	tip_pct
smoker								
No	57	26.41	1.50	No	Sat	Dinner	2	0.056797
0	16.99	1.01	No	Sun	Dinner	2	0.059447
48	28.55	2.05	No	Sun	Dinner	3	0.071804
146	18.64	1.36	No	Thur	Lunch	3	0.072961
130	19.08	1.50	No	Thur	Lunch	2	0.078616
Yes	237	32.83	1.17	Yes	Sat	Dinner	2	0.035638
102	44.30	2.50	Yes	Sat	Dinner	3	0.056433
187	30.46	2.00	Yes	Sun	Dinner	5	0.065660
210	30.06	2.00	Yes	Sat	Dinner	3	0.066534
240	27.18	2.00	Yes	Sat	Dinner	2	0.073584

2)调用函数式添加函数参数

tips.groupby(['smoker', 'day']).apply(top, n=1, column='total_bill')
total_bill	tip	smoker	day	time	size	tip_pct
smoker	day								
No	Fri	99	12.46	1.50	No	Fri	Dinner	2	0.120385
Sat	111	7.25	1.00	No	Sat	Dinner	1	0.137931
Sun	6	8.77	2.00	No	Sun	Dinner	2	0.228050
Thur	149	7.51	2.00	No	Thur	Lunch	2	0.266312
Yes	Fri	92	5.75	1.00	Yes	Fri	Dinner	2	0.173913
Sat	67	3.07	1.00	Yes	Sat	Dinner	1	0.325733
Sun	172	7.25	5.15	Yes	Sun	Dinner	2	0.710345
Thur	196	10.34	2.00	Yes	Thur	Lunch	2	0.193424

3)使用apply时,不用分组键做index:

#压缩分组键, 可以看到所得到的对象具有分组键所形成的分层索引以及每个原始对象的索引。你可以通过向groupby传递group_keys=False来禁用这个功能:
tips.groupby('smoker', group_keys=False).apply(top)
total_bill	tip	smoker	day	time	size	tip_pct
57	26.41	1.50	No	Sat	Dinner	2	0.056797
0	16.99	1.01	No	Sun	Dinner	2	0.059447
48	28.55	2.05	No	Sun	Dinner	3	0.071804
146	18.64	1.36	No	Thur	Lunch	3	0.072961
130	19.08	1.50	No	Thur	Lunch	2	0.078616
237	32.83	1.17	Yes	Sat	Dinner	2	0.035638
102	44.30	2.50	Yes	Sat	Dinner	3	0.056433
187	30.46	2.00	Yes	Sun	Dinner	5	0.065660
210	30.06	2.00	Yes	Sat	Dinner	3	0.066534
240	27.18	2.00	Yes	Sat	Dinner	2	0.073584

欢迎交流!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值