一、分组Groupby
使用方式:df.groupby([分组的依据])[分组的数据]
例如,对不同学校和性别的学生身高分组:
df.groupby(['School', 'Gender'])['Height']
练一练:请根据上下四分位数分割,将体重分为high、normal、low三组,统计身高的均值。
low = df['Weight'].quantile(0.25)
high = df['Weight'].quantile(0.25)
condition1 = df['Weight']>high
condition2 = df['Weight']<low
condition3 = low< df['Weight']<high #这一块有问题,还没来得及问
df_high = df.groupby(condition1)['Height'].mean()
df_mid = df.groupby(condition3)['Height'].mean()
df_low = df.groupby(condition2)['Height'].mean()
通过 ngroups
属性,可以得到分组个数:
a = df.groupby(['School', 'Gender'])
a.ngroups
Out[33]: 8
进一步,通过 groups
属性,可以返回从 组名 映射到 组索引列表 的字典
a.groups.keys()
Out[37]: dict_keys([('Fudan University', 'Female'), ('Fudan University', 'Male'), ('Peking University', 'Female'), ('Peking University', 'Male'), ('Shanghai Jiao Tong University', 'Female'), ('Shanghai Jiao Tong University', 'Male'), ('Tsinghua University', 'Female'), ('Tsinghua University', 'Male')])
也可以直接通过 drop_duplicates
就能知道具体的组类别,其结果和上面的一致:
In [11]: df[['School', 'Gender']].drop_duplicates()
Out[11]:
School Gender
0 Shanghai Jiao Tong University Female
1 Peking University Male
2 Shanghai Jiao Tong University Male
3 Fudan University Female
4 Fudan University Male
5 Tsinghua University Female
9 Peking University Female
16 Tsinghua University Male
练一练:上一小节介绍了可以通过 drop_duplicates
得到具体的组类别,现请用 groups
属性完成类似的功能。
a = df.groupby(['School', 'Gender'])
list(a.groups.keys())
Out[43]:
[('Fudan University', 'Female'),
('Fudan University', 'Male'),
('Peking University', 'Female'),
('Peking University', 'Male'),
('Shanghai Jiao Tong University', 'Female'),
('Shanghai Jiao Tong University', 'Male'),
('Tsinghua University', 'Female'),
('Tsinghua University', 'Male')]
二、聚合函数
定义:聚合函数是对一组值执行计算并返回单一的值。在我们这节中,指的是对分组的序列返回其统计特征。
练一练:请查阅文档,明确 all/any/mad/skew/sem/prod
函数的含义。
all() #返回所有元素是否为真
any() # 返回其中任意一个元素是否为真
mad() # 根据平均值计算平均绝对距离差
skew() # 返回峰度
sem() # 返回所请求轴上的平均值的无偏标准误差
prod() # 返回乘积
agg方法:增加了内置聚合函数的灵活性
-
使用多个聚合函数:用列表的形式将内置聚合函数以字符串的形式输入。
gb = df.groupby('Gender')[['Height', 'Weight']] gb.agg(['sum', 'idxmax', 'skew']) Out[25]: Height Weight sum idxmax skew sum idxmax skew Gender Female 21014.0 28 -0.219253 6469.0 28 -0.268482 Male 8854.9 193 0.437535 3929.0 2 -0.332393
-
对特定的列使用特定的聚合函数:用字典的形式
gb.agg({'Height':['mean','max'], 'Weight':'count'}) Out[26]: Height Weight mean max count Gender Female 159.19697 170.2 135 Male 173.62549 193.9 54
练一练:请使用【b】中的传入字典的方法完成【a】中等价的聚合任务。
gb.agg({'Height':['sum', 'idxmax', 'skew'],'Weight':['sum', 'idxmax', 'skew']})
-
使用自定义函数:保证返回值为标量
gb.agg(lambda x: x.mean()-x.min()) #求极差
练一练:在
groupby
对象中可以使用describe
方法进行统计信息汇总,请同时使用多个聚合函数,完成与该方法相同的功能。gb.agg(['count','mean','std','min',('25%',lambda x:x.quantile(0.25)),('50%','quantile'),('75%',lambda x:x.quantile(0.75)),'max'])
-
对聚合结果重命名:将函数的输入改为元组,第一个元素为新的名字;使用对一个或者多个列使用单个聚合的时候,重命名需要加方括号,否则就不知道是新的名字还是手误输错的内置函数字符串:
gb.agg([('my_sum', 'sum')])
三、变换和过滤
-
transform函数
transform函数是针对每一列进行操作的,返回值为同长度的序列。
练一练:在
groupby
对象中,rank
方法也是一个实用的变换函数,请查阅它的功能并给出一个使用的例子。#rank函数返回某一特征的排名等级df.groupby('Gender')[['Height', 'Weight']].rank() #按性别分组后,对身高和体重分别排名
练一练:对于
transform
方法无法像agg
一样,通过传入字典来对指定列使用特定的变换,如果需要在一次transform
的调用中实现这种功能,请给出解决方案。#自己没想出来,参考天国之影大佬的 def my_func(method_dict): def my_(x): method = method_dict[x.name] if method == 'standardized': return (x-x.mean())/x.std() elif method == 'max': return x.max() return my_ gb.transform(my_func({'Height':'standardized', 'Weight':'max'})).head()
-
过滤
分组中的过滤是对组的过滤,使用filter函数完成相关操作。