Pandas的分组操作与SQL语句的group by 基本相差不大,相互之间可以联想理解。在分组以后可以进行一下操作:
- 聚合
agg()
- 计算汇总统计转换 - 转换
transform()
- 执行一些特定于组的操作过滤 - - 过滤
filter()
- 在某些情况下丢弃数据
import pandas as pd
import numpy as np
data = {
'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
'Points':[876,789,863,673,741,812,756,788,694,701,804,690]
}
df = pd.DataFrame(data)
输出df可得
Team Rank Year Points
0 Riders 1 2014 876
1 Riders 2 2015 789
2 Devils 2 2014 863
3 Devils 3 2015 673
4 Kings 3 2014 741
5 kings 4 2015 812
6 Kings 1 2016 756
7 Kings 1 2017 788
8 Riders 2 2016 694
9 Royals 4 2014 701
10 Royals 1 2015 804
11 Riders 2 2017 690
遍历分组后的对象
grouped = df.groupby('Year')
for name,group in grouped:
print (name)
print (group)
运行结果
2014
Team Rank Year Points
0 Riders 1 2014 876
2 Devils 2 2014 863
4 Kings 3 2014 741
9 Royals 4 2014 701
.
.
.
.
2017
Team Rank Year Points
7 Kings 1 2017 788
11 Riders 2 2017 690
使用聚合函数
# groupby()中可以太假一个值,可以使用列表形成二级索引
# 其中的as_index 可以让一级索引是否都填充,默认是True
df.groupby('Team').agg([np.sum,np.mean])
运行结果
Rank Year Points
sum mean sum mean sum mean
Team
Devils 5 2.500000 4029 2014.500000 1536 768.000000
Kings 5 1.666667 6047 2015.666667 2285 761.666667
Riders 7 1.750000 8062 2015.500000 3049 762.250000
Royals 5 2.500000 4029 2014.500000 1505 752.500000
kings 4 4.000000 2015 2015.000000 812 812.000000
当然在聚合的时候可以单独选择某一列的值进行查看,例如我选择Rank这一列
df.groupby('Team').agg([np.sum,np.mean])['Rank']
值得注意的是当我们进行聚合的时候的时候查看其索引值,会发现他返回的是一个多层索引(MultiIndex)
mult = df.groupby(['Team','Year']).agg([np.sum,np.mean])
print(mult.index)
输出结果为
MultiIndex([('Devils', 2014),
('Devils', 2015),
( 'Kings', 2014),
( 'Kings', 2016),
( 'Kings', 2017),
('Riders', 2014),
('Riders', 2015),
('Riders', 2016),
('Riders', 2017),
('Royals', 2014),
('Royals', 2015),
( 'kings', 2015)],
names=['Team', 'Year'])
那么既然是多层索引怎么进行取值,查找那?这里依然用到查找方法.loc
。
- 当传入元组的时候(K1, K2),它查询的是两个级别的索引,即K1是第一级别,K2是第二级别
- 当传入列表的时候 [K1 , K2] , 它查询的是同级索引
mult.loc[('Devils',2015)]
mult.loc[('Devils','Riders')]
输出结果为
Rank sum 3
mean 3
Points sum 673
mean 673
Name: (Devils, 2015), dtype: int64
---------------------------------------
Rank Points
sum mean sum mean
Team Year
Devils 2014 2 2 863 863
2015 3 3 673 673
Riders 2014 1 1 876 876
2015 2 2 789 789
2016 2 2 694 694
2017 2 2 690 690
当然在使用的时候依旧可以使用单独的选择某一列进行单独显示:
mult.loc[['Devils','Riders'],'Rank']
使用过滤函数
filter = df.groupby('Team').filter(lambda x: len(x) >= 3)
输出如下(出现大于三次的)
Team Rank Year Points
0 Riders 1 2014 876
1 Riders 2 2015 789
4 Kings 3 2014 741
6 Kings 1 2016 756
7 Kings 1 2017 788
8 Riders 2 2016 694
11 Riders 2 2017 690
使用转换函数
grouped = df.groupby('Team')
score = lambda x: (x - x.mean()) / x.std()*10
print (grouped.transform(score))
输出如下
Points Rank Year
0 12.843272 -15.000000 -11.618950
1 3.020286 5.000000 -3.872983
2 7.071068 -7.071068 -7.071068
.
.
关键是在聚合的时候注意层次级别!