文章目录
Pandas数据分析-Task4
记录DataWhale的Pandas数据分析的学习过程,使用的教材为 joyful-pandas。
Task4是pandas的分组相关的知识(相比前几天任务量小一些,菜鸡终于能喘口气了),内容基本可以分为三个部分,第一部分介绍groupby()函数的基本使用;第二部分介绍分组的三大操作:聚合agg()、变换transform()、以及过滤filter();第三部分介绍apply()函数在分组中的应用。本篇文章中所有的代码示例中用到的原始文件都可以在 此链接中下载。
分组函数
分组基本操作
pandas的分组操作使用的是groupby()函数,其一般的使用方法为:
df.groupby(分组依据)[数据来源].操作函数
比如,我们有学校学生情况的表格‘learn_pandas.csv’,要根据性别分类后统计身高的均值:
#语句1
df = pd.read_csv('data/learn_pandas.csv')
df.groupby('Gender')['Height'].mean()
语句1是最简单的根据一个列进行分组,如果要根据多个列进行分组,直接把多个列的名字组成字符串列表,当作groupby()函数的输入参数即可。
语句1其实是groupby的一个特殊情况,实际上,只有当分组条件是列表中的列时,才能使直接用列名字符做分组依据,直接用df中的列名做分组只是一个记号,等于传入的是一整列的值,也即,语句1实际上进行的操作为:
df = pd.read_csv('data/learn_pandas.csv')
df.groupby(df['Gender'])['Height'].mean()
知道了这个原理,我们就可以很方便扩展groupby()函数的输入,其输入参数不一定非要是df中的列,也可以是自己构造的一个数组,只要数组的长度和df的长度一致即可。所以,我们也可以构造逻辑表达式进行分组,例如,根据学生体重是否超过总体均值来分组:
condition=df.Weight > df.Weight.mean()#condition是一个长度与df相等的布尔Series.
df.groupby(condition)['Height'].mean()
Groupby对象
groupby()函数返回的是一个Groupby对象,教材介绍了几个常用的属性及方法:
- ngroups属性:查看分为了多少组。
- groups属性:返回从组名映射到组索引列表的字典。
- size():查看每个组元素的个数。
- get_group():获取一个组具体的内容,输入参数是这个组的index。
练一练
题目:可以通过drop_duplicates 得到具体的组类别,现请用groups 属性完成类似的功能。
思路:groups属性返回字典,字典的key即是不重复的组合。
df = pd.read_csv('data/learn_pandas.csv')
df[['Gender','School']].drop_duplicates(['Gender','School'])#使用drop_duplicates()方法
pd.DataFrame(df.groupby(['Gender','School']).groups.keys(),columns=['Gender','School'])#groupby结合groups属性。
聚合、变换、过滤
groupby对象无法直接显示,只能通过操作函数返回数据。其返回的数据可分为三类:标量,序列,DataFrame。分别对应了三类操作:聚合、变换、过滤。
聚合方法-agg()
聚合函数多为统计函数,从一组或几组序列中返回一个标量值。pandas有一些内置的聚合函数:max/min/mean/median/count,可以直接调用。
练一练
问题:请查阅文档,明确all/any/mad/skew/sem/prod 函数的含义。
- any(): Return True if any value in the group is truthful, else False。大概意思是如果组内有truthful的值就返回True。
- all():Return True if all values in the group are truthful, else False.组内所有元素都是truthful,返回True。
- mad():返回组内元素的绝对中位差。先计算出数据与它们的中位数之间的残差,MAD就是这些偏差的绝对值的中位数。MAD比方差鲁棒性更好。
- skew():组内数据的偏度。
- sem():组内数据的均值标准误差。
- prod() :组内所有元素的乘积。
简单的内置聚合函数无法完成更复杂的操作,agg()方法可进行更复杂的聚合操作。具体为:
1.对一个分组同时使用多个聚合函数:把多个内置聚合函数的名称字符组成列表。
gb = df.groupby('Gender')[['Height', 'Weight']]
gb.agg(['sum', 'idxmax', 'skew'])#把多个内置聚合函数的名称字符组成列表。
在练习的时候发现,如果agg()函数中只输入单个的内置聚合函数名称字符,最后的输出是不会显示列索引的。只有聚合函数名称字符加上[]括号以后才会显示列索引。
gb.agg('mean') #'mean'没加[],只显示一层的列索引。
> Height Weight
Gender
Female 159.19697 47.918519
Male 173.62549 72.759259
gb.agg(['mean'])#'mean'加了[],最后的结果是两层的类索引。
> Height Weight
mean mean
Gender
Female 159.19697 47.918519
Male 173.62549 72.759259
2.对特定的列使用特定的聚合函数:列名字符和函数名称字符组成的字典。
gb.agg({
'Height':['mean','max'], 'Weight':'count'})#列名字符和函数名称字符组成的字典
练一练
问题:请使用2中的传入字典的方法完成1中等价的聚合任务。
gb.agg({
'Height':['mean','max','min'],'Weight':['mean','max','min']})
3.自定义的聚合函数:传入函数的参数是之前数据源中的列,逐列进行计算
gb.agg(lambda x: x.mean()-x.min())#x代表的是分组后的一列。
练一练
问题:在groupby 对象中可以使用describe 方法进行统计信息汇总,请同时使用多个聚合函数,完成与该方法相同的功能。
思路:使用agg汇集多个基本的聚合函数即可,在做的时候发现分位数函数不能直接输入名字,因为要计算3个不同的分位数,最后使用lambda匿名函数完成分位数功能,并重命名。
gb.describe()
> Height Weight