分组级运算和转换
聚合只是分组运算的一种,本节将介绍transform和apply方法,它们将能执行更多的分组运算。
假设我们想为一个DataFrame添加一个用于存放索引分组平均值的列,按照之前的做法是:
#先构建一个DataFrame
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
data = {"data1":np.random.randn(5),"data2":np.random.randn(5),"key1":["a","a","b","b","a"],"key2":["one","two","one","two","one"]}
df = DataFrame(data,columns =['data1','data2','key1','key2' ])
df
#通过groupby分组求平均组成新列。
k1_means = df.groupby("key1").mean().add_prefix("mean_")
k1_means
#再合并
pd.merge(df,k1_means,left_on='key1',right_index = True)
然而transform则是将函数应用到各个分组。
df.groupby("key1").transform(np.mean)
如果想要得到从各组中减去平均值。即距平化函数处理。我们先写出这个函数,然后应用这个函数到各个分组:
def demean(arr):
return arr-arr.mean()
demeaned = df.groupby("key1").transform(demean)
apply:一般性的“拆分-应用-合并”
跟aggregate一样,transform也是一个有着严格条件的特殊函数:传入的函数只能产生两种结果.要么产生一个可以广播的标量值(如np.mean),要么产生一个相同大小的结果数组.最一般化的GroupBy方法是apply.本节剩余部分将重点讲解.apply会将待处理的对象拆分成多个片段,然后对齐片段调用传入的函数,最后尝试将各片段组合到一起。
所以对比下transform和apply的区别:
transform是对每组的数据分别处理后应用到每个数据。
而apply则是分组后比如四组,对四个小组分别应用函数,然后数据组合在一起。而不会覆盖到每个数据。
比如取出每组的data1的值最大的列:(sort_index现已改为sort_values)
分位数和桶分析
前面章节说过将数据拆分成多块(cut和qcut),将这些与groupby结合,即可实现对数据的桶或分位数分析。来看:
#将df装入长度相等的桶中(labels=False则分组信息就默认用0123编号代替)
factor = pd.cut(df.data1,4)
#定义一个函数返回分组的最小值,最大值,个数和平均值
def get_stats(group):
return{'min':group.min(),'max':group.max(),'count':group.count(),'mean':group.mean()}
#cut返回的Factor对象可直接用于groupby。即按找cut分组。
grouped = df.data1.groupby(factor)
#对分组后的数据应用函数,返回各个分组的信息。
grouped.apply(get_stats).unstack()
透视表和交叉表
透视表根据一个或多个键对数据进行聚合.并根据行和列上的分组键将数据分配到各个矩形区域中.在Python和pandas中.可以通过本章所介绍的groupby功能以及(能够利用层次化索引的)重塑运算制作透视表。DataFrame有一个pivot_table方法,此外还有一个顶级的pandas.pivot_ table函数.除能为groupby提供便利之外,pivot_ table还可以
添加分项小计(也叫做margins)。
#取data1数据平均值(pivot_table默认),按行key1,列key2显示,margins添加分组统计(平均值)
#注意是index和columns 不再是rows和cols
df.pivot_table(['data1','data2'],index=['key1'],columns='key2',margins=True)
注意看0.458889是(1.970981 - 0.297157 - 0.297157)/3得来的,因为有两个(a,one)。
默认是平均值,使用其他的传给aggfunc参数即可,如aggfunc=len。
privot_table的参数
交叉表:crosstab
交叉表(cross-tabulation,简称crosstab)是一种用于计算分组频率的特殊透视表。下面这个范例数据很典型,取自交叉表的Wikipedia页:
如果想根据性别和用手习惯统计汇总,虽然可以用pivot_table实现,但是用pandas.crosstab函数更方便:
crosstab的前两个参数可以是数组、Series或数组列表。再比如对小费数据集:
pd.crosstab([tips.time, tips.day],tips.smoker, margins=True)
总结
继续介绍了数组聚合分组运算,重点介绍了transform和apply方法以及分位数和桶分析与groupby结合,以及一定情况下使用透视表和交叉表更为方便的显示。
微信公众号:BrainZou
欢迎关注,一起学习。
网友评论