分组
想要实现分组操作,必须明确三个要素:分组依据 、 数据来源 、 操作及其返回结果 。
df.groupby(分组依据)[数据来源].使用操作
需要根据多个维度进行分组,只需在 groupby 中传入相应列名构成的列表即可
- 当 size 作为 DataFrame 的属性时,返回的是表长乘以表宽的大小,但在 groupby 对象上表示统计每个组的元素个数
- 通过 get_group 方法可以直接获取所在组对应的行,此时必须知道组的具体名字
gb = df.groupby(['School', 'Grade'])
gb.get_group(('Fudan University', 'Freshman')).iloc[:3, :3]
# 练一练
#请根据上下四分位数分割,将体重分为high、normal、low三组,统计身高的均值。
df['Weight Level']='normal'
df.loc[df['Weight']> df.Weight.quantile(0.75),'Weight Level']='high'
df.loc[df['Weight']< df.Weight.quantile(0.25),'Weight Level']='low'
df.groupby('Weight Level')['Height'].mean()
聚合函数
首先要了解一些直接定义在groupby对象的聚合函数,因为它的速度基本都会经过内部的优化,使用功能时应当优先考虑。根据返回标量值的原则,包括如下函数: max/min/mean/median/count/all/any/idxmax/idxmin/mad/nunique/skew/quantile/sum/std/var/sem/size/prod 。
明确 all/any/mad/skew/sem/prod 函数的含义
- all和any一般用于bool值列 , all表示分组后每一组中所有值都为True则返回True , 有一个False就返回False
- any与all类似 , 表示bool值列中只要有一个True则返回true , 只有全为False才会返回False
- mad(mean absolute deviation)平均绝对离差
- skew(skewness)偏度 , 用来反映分组后每组数据分布的偏态程度 , 正值为右偏 , 绝对值越大 , 偏度越高
- 类似的 , kurt(kurtosis)峰度 , 用来反映分组后每组数据分布的平尖程度 , 正值为尖峰分布 , 值越大越尖 , 负值为扁平程度 , 绝对值越大越平
agg函数解决四类问题
- 【a】使用多个函数
gb.agg(['sum', 'idxmax', 'skew'])
- 对特定的列使用特定的聚合函数
gb.agg({'Height':['mean','max'], 'Weight':'count'})
# 练一练
gb=df.groupby('Gender')[['Height', 'Weight']]
gb.agg({'Height':['sum', 'idxmax', 'skew'],'Weight':['sum', 'idxmax', 'skew']})
- 使用自定义函数:在 agg 中可以使用具体的自定义函数, 需要注意传入函数的参数是之前数据源中的列,逐列进行计算 。
gb.agg(lambda x: x.mean()-x.min())
#练一练
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([('range', lambda x: x.max()-x.min()), ('my_sum', 'sum')])
变换与过滤
在 groupby 对象中,定义了 filter 方法进行组的筛选,其中自定义函数的输入参数为数据源构成的 DataFrame 本身,在之前例子中定义的 groupby 对象中,传入的就是 df[['Height', 'Weight']]
练习题
1
#过滤不超过2次的
countryCount=df.groupby('Country')['Brand'].count()
df_drop=df.drop(df[df['Country'].isin(countryCount[countryCount<=2].index)].index,axis=0)
df_drop.groupby('Country')['Price'].agg(['mean',('Cov',lambda x: x.std()/x.mean()),'count'])
#按照表中位置的前三分之一、中间三分之一和后三分之一分组,统计 Price 的均值。
W=df_drop.Price
conda=W.mask(W<W.quantile(0.333),'low').mask(W>W.quantile(0.6667),'high').mask((W>=W.quantile(0.3333))&(W<=W.quantile(0.6667)),'middle')
df_drop.groupby(conda)['Price'].mean()