(作者:陈玓玏)
在SQL中,我们可以用分析函数轻松实现变量分组后的组内max、min等结果的统计,而在Python中,使用pandas来实现这些功能也是非常简单的。
pandas中也有groupby函数,能够根据特定的列将所有数据进行分组,并通过agg方法对选定的列进行分组统计,内置的统计方法有max、min、mean、var、count等,还能通过lambda或者def自定义匿名函数或者函数,灵活地实现各类数据结果的统计。
零、最好的写法
下面给出一个目前认为最好用的写法:
get_count = lambda x:x.count(if x>10)
data = data[col1].groupby(data[col2]).agg({'maxValue':'max','minValue':'min','filterCount':get_count}).reset_index()
这段代码的输出结果将会得到根据col2进行分组后,col1的组内最大值、最小值以及组内大于10的值的个数,加上col2这一列,共同构成一个新的DataFrame对象。
如果你想知道这么写的理由,就请看下面详解的写这样的代码时的几个坑:
1、为什么要用agg
如果你不用agg,也可以实现同样的功能,因为Pandas自带了max、min、mean这些聚合函数,用法如下:
data = data[col1].groupby(data[col2]).max()
data = data[col1].groupby(data[col2]).mean()
data = data[col1].groupby(data[col2]).min()
但是这样就没办法通过自定义的聚合函数来实现自定义的变量统计了,而用agg可以传入自定义的聚合函数。
2、为什么agg里面要放字典
agg里面可以不传字典,但是新生成的列是不能直接生成你想要的列名的。如果你想要定义列名,那你得这么做:
#先初始化列为1,再给这一列传入统计后的值
data['max'] = 1
data['max'] = data[col1].groupby(data[col2]).agg('max').reset_index()
print(data)
用这种方法,如果同时实现最大值、最小值、均值、计数等参数统计的话,需要写八行代码,而在agg中传入字典参数,同时定义列名和所用的聚合函数,只需要一列就能完成了,甚好。
3、为什么要写reset_index
这个问题比较有意思。如果不加reset_index,你可以直接输出结果观察一下,你会发现结果看起来很像一个DataFrame对象,但是当你试着在其中根据索引取列时,会报错。因为不用reset_index时输出的是一个numpy.series.group对象(大概是这样?手写记不太清了,感兴趣的可以自己试试)。
除此之外,你会发现输出结果的第一列看似是DataFrame的行索引,但其实它是一列,并且第一行也不是列索引,而是数据。如果你想把列改成索引,请看下面的代码:
data.set_index('max', inplace=True) # column 改为 index
data.reset_index(level=0, inplace=True) #设置索引
这就能解释为什么要用reset_index了吧?为了一步到位地输出一个可操作性最强的结果。
四、describe函数
describe是一个极好用的函数,能够直接输出最大值、最小值、均值、方差、分位数等等,不仅限于四分位数哦,所以不想自己一个一个统计的时候,用这个是极好的选择。
代码如下:
#对分组做统计
data[col1].groupby(data[col2]).describe()
#对总体做统计
data.describe()
五、merge函数
通常情况下,我们在造变量时会希望对不同的业务变量分别求分组后的统计分量,那么对各统计结果需要进行融合,就可以用merge函数。
newData = pd.merge(data1,data2,on='id')
merge的原理其实和SQL中的join是一样的,如果直接写on,就表示以这一列为基准做两个DataFrame的匹配,但是要求这一列必须同时存在于两个对象中。如果两个对象中的id字段名称不同,那么规定好left_on和right_on变量即可。