Pandas分组(GroupBy)

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
					.
					.

关键是在聚合的时候注意层次级别!

猜你喜欢

转载自blog.csdn.net/qq_44091773/article/details/106079418