本文是【统计师的Python日记】第10天的日记
回顾一下:
原文复习(点击查看):
今天将带来第10天的学习日记。
目录如下:
前言
1. 聚合运算
(1)groupby:按照变量进行分组
(2)按照函数进行分组
(3)用agg()自定义聚合函数
2. 数据透视表
(1)pivot_table()方法
(2)交叉表crosstab
统计师的Python日记【第10天:数据聚合】
前言
根据我的Python学习计划:
Numpy → Pandas → 掌握一些数据清洗、规整、合并等功能 → 掌握正则表达式 → 掌握类似与SQL的聚合等数据管理功能 → 能够用Python进行统计建模、机器学习等分析技能 → 能用Python打印出100元钱 → 能用Python帮我洗衣服、做饭 → 能用Python给我生小猴子......
其实前面在学合并的时候已经学过类似的功能了:左连接、右连接、内连接、全连接(第6天:数据合并)。今天来学数据的聚合。什么叫聚合呢?来看个例子:
有一份数据,数据名为family:
变量如下:
从这份名单中大概能猜到,fam1有三个成员,可能是一个三口之家;fam2有5位成员,也许是四世同堂;fam2有2位成员,应该是两口子,不过这不重要。
现在,想知道每个家庭的成员平均月收入,应该如何处理?
学过SQL的人知道,典型的SQL查询语句应该是:
select mean(salary) from family group by fam
从数据family这份数据中,找出每个fam group下的mean(salary)。这是一个典型的数据聚合的例子,现在如果想用Pandas来实现,应该如何处理?
1. 聚合运算
(1)groupby:按照变量进行分组
要实现这个目的,使用 groupby 语句即可。
按照下图所示,进行两步操作:
于是就得到了聚合函数的第一种写法:
family['salary'].groupby(family['fam']).mean()
大图解释:
结果为:
这个例子是对fam进行分组求mean(salary),也就是对fam进行groupby,当然也可以对两个变量一起进行groupby,比如对salary按照fam、gender分组求mean:
注意标红的中括号,这是传入的是一个list了,结果如下:
不过我觉得这样看起来特别不美丽,可以用unstack变成透视表,这个在第五天(第5天:Pandas,露两手)已经学过了:
第二种写法
还有一种写法是这样的:family.groupby('fam')['salary'].mean()
结果为:
一次性对多个变量进行groupby这么写:
family.groupby( [ ‘fam’, ‘gender’ ] )[‘salary’]
不指明salary,则代表对family所有连续变量进行groupby。后面其他功能都与第一种写法类似。
这个第二种写法是第一种的语法糖,什么叫语法糖?简单来说就是编程语言中可以更容易的表达一个操作的语法,它可以使程序员更加容易去使用这门语言:操作可以变得更加清晰、方便,或者更加符合程序员的编程习惯。
(2)按照函数进行分组
刚刚是对变量进行groupby,还可以直接对函数进行groupby。函数的对象是索引。比如oct(x)这个函数是将x转换成八进制,那么如果对oct进行groupby,比如:
family.groupby(oct).count()
那么就是对原数据的索引求八进制,再进行count:
如果索引是字符串,还可以有更多玩法,比如数据是这样的:
索引是每个人的名字,那么现在可以对名字的占位长度进行GroupBy:
好吧,暂时就想到这么多。
(3)用agg()自定义聚合函数
前面的聚合函数:mean()/ sum()/ count()等等,都是内置的,其实也可以自定义,自定义函数之后,要结合agg使用。比如定义一个最大值的两倍:
def max2(ser):
return 2*ser.max()
family.groupby('fam')['salary'].agg(max2)
结果为:
如果自定义的聚合函数为fun(),那么groupby中要以agg(fun)的形式使用。
agg()不仅可以发挥自定义聚合函数的作用,还可以一次性对多个函数进行聚合运算:
family.groupby('fam')['salary'].agg(['mean','sum', max2])
结果为:
注意调用的函数不加引号。
这里的列名还可以改,比如不想用max2这个列名,想用2*max,在自定义函数的时候因为不能以数字开头所以只能写成max2,那么这里可以用(‘2*max’, max2)来改名字:
family.groupby('fam')['salary'].agg(['mean','sum', (‘2*max’,max2)])
还可以对不同的列应用不同的聚合函数,使用字典可以完成 {列1:函数1, 列2:函数2},然后再用agg()包起来:
family.groupby('fam')['salary'].agg({'salary':'mean','gender':'count'})
2. 数据透视表
在第5天的日记中,提到过“数据透视表”(第5天:Pandas,露两手):
现在看来,这个unstack()完全不能算“透视表”,因为今天要学pivot_table()方法和pandas.pivot_table()方法。
(1)pivot_table()方法
比如,以fam这个列变量维度进行透视:
family.pivot_table(columns='fam')
以fam、gender这两个维度进行透视:
添加margins=True可以为透视表添加总计:
除了margins选项,还有其他选项可以辅助:
(2)交叉表crosstab
因为是统计师,经常会做卡方检验,所以对列联表或者是交叉表很熟悉,就是看交叉分组下的频数。现在想做一个fam和gender的列联表:
pd.crosstab(family.fam, family.gender,margins=True)
也可以做成三维的:
pd.crosstab( [family.salary, family.fam],family.gender, margins=True )
好啦,到今天已经是第10天了,Python的数据处理已经结束,下一篇日记打算开始学习Python的统计分析模块。在此之前您还有什么建议请给我留言。