第四章 分组

import numpy as np
import pandas as pd

分组模式及其对象

1. 分组的一般模式

df.groupby(分组依据)[数据来源].使用操作

2. 分组依据的本质

① 单个维度、多个维度的分组,直接在groupby中传入相应列名构成的列表即可。

df.groupby(['School','Gender'])['Height'].mean()

第四章 分组
② 通过一定的复杂逻辑来分组

#先写出分组条件
condition = df.Weight > df.Weight.mean()
df.groupby(condition)['Height'].mean()

第四章 分组
练一练
请根据上下四分位数分割,将体重分为high、normal、low三组,统计身高的均值。

def fenzu_height(x):
    if x > df['Height'].quantile(0.75):
        return "high"
    elif x < df['Height'].quantile(0.25):
        return "low"
    else:
        return "normal"
bool = df['Height'].apply(fenzu_height)
df.groupby(bool)['Height'].mean()

第四章 分组
首先写一个函数分出三种情况,再对要求的身高那一列的数据apply这个函数【先写好分组条件】
最后产生的结果就是按照条件列表中元素的值来分组,下面用随机传入字母序列来验证这一想法
第四章 分组
如果传入多个序列进入 groupby ,那么最后分组的依据就是这两个序列对应行的唯一组合
第四章 分组
通过 drop_duplicates 就能知道具体的组类别

df[['School', 'Gender']].drop_duplicates()

第四章 分组

3. Groupby对象

gb = df.groupby(['School', 'Grade'])

具体做分组操作时,所调用的方法都来自于 pandas 中的 groupby 对象,这个对象上定义了许多方法,也具有一些方便的属性。
① 通过 ngroups 属性,可以得到分组个数

gb.ngroups
#16

② 通过 groups 属性,可以返回从 组名 映射到 组索引列表 的字典:

res = gb.groups
# 字典的值由于是索引,元素个数过多,此处只展示字典的键
res.keys()

第四章 分组
练一练
上一小节介绍了可以通过 drop_duplicates 得到具体的组类别,现请用 groups 属性完成类似的功能。

gb = df.groupby(['School','Grade'])
res = gb.groups
res.keys()

第四章 分组
③ 当 size 作为 DataFrame 的属性时,返回的是表长乘以表宽的大小,但在 groupby 对象上表示统计每个组的元素个数

gb.size()

第四章 分组
通过 get_group 方法可以直接获取所在组对应的行,此时必须知道组的具体名字

gb.get_group(('Fudan University', 'Freshman'))

第四章 分组

二、聚合函数

1.内置聚合函数

在介绍agg之前,首先要了解一些直接定义在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 表示bool值列中只要有一个True则返回true , 只有全为False才会返回False非0都是Ture!!!
    第四章 分组
  • mad(mean absolute deviation)平均绝对离差 , 用于统计学中对分组后的每组数据做离散程度分析的指标之一 M i = 1 n ∑ k = 1 n ∣ x k − x ˉ ∣ M_i=\frac1n\sum_{k=1}^n|x_k-\bar x| Mi​=n1​∑k=1n​∣xk​−xˉ∣
    第四章 分组
  • skew(skewness)偏度 , 用来反映分组后每组数据分布的偏态程度 , 正值为右偏 , 绝对值越大 , 偏度越高
    S K i = n n − 1 ∑ k = 1 n ( x k − x ˉ ) 2 ( n − 2 ) ( ∑ k = 1 n ( x k − x ˉ ) 2 ) 3 2 SK_i=\frac{n\sqrt{n-1}\sum_{k=1}^n(x_k-\bar x)^2}{(n-2)(\sum_{k=1}^n(x_k-\bar x)^2)^{\frac32}} SKi​=(n−2)(∑k=1n​(xk​−xˉ)2)23​nn−1 ​∑k=1n​(xk​−xˉ)2​
    第四章 分组
  • sem(standard error of mean)均值标准误差 , 描述的是多个均值样本的标准差,体现均值抽样分布的离散程度,反映样本均值之间的差异
    设样本无偏估计标准差为s , 样本大小为N , 则分组后每组的sem可表示为
    S E M i = s N SEM_i=\frac{s}{\sqrt N} SEMi​=N ​s​
    第四章 分组
  • prod(product)连乘 , 每组prod表示为
    P R O D i = Π k = 1 n x k PROD_i=\Pi_{k=1}^nx_k PRODi​=Πk=1n​xk​
    第四章 分组
    这些聚合函数当传入的数据来源包含多个列时,将按照列进行迭代计算:
    第四章 分组

2. agg方法

虽然在 groupby 对象上定义了许多方便的函数,但仍然有以下不便之处:

  • 无法同时使用多个函数
  • 无法对特定的列使用特定的聚合函数
  • 无法使用自定义的聚合函数
  • 无法直接对结果的列名在聚合前进行自定义命名

下面说明如何通过 agg 函数解决这四类问题:
【a】使用多个函数
当使用多个聚合函数时,需要用列表的形式把内置聚合函数对应的字符串传入,先前提到的所有字符串都是合法的。
第四章 分组
此时的列索引为多级索引,第一层为数据源,第二层为使用的聚合方法,分别逐一对列使用聚合,因此结果为6列。
【b】对特定的列使用特定的聚合函数
对于方法和列的特殊对应,可以通过构造字典传入 agg 中实现,其中字典以列名为键,以聚合字符串或字符串列表为值。
第四章 分组
练一练
请使用【b】中的传入字典的方法完成【a】中等价的聚合任务。

gb.agg({'Height':['sum','idxmax','skew'],'Weight':['sum','idxmax','skew']})

第四章 分组
【c】使用自定义函数
在 agg 中可以使用具体的自定义函数, 需要注意传入函数的参数是之前数据源中的列,逐列进行计算 。下面分组计算身高和体重的极差:
第四章 分组
练一练
在 groupby 对象中可以使用 describe 方法进行统计信息汇总,请同时使用多个聚合函数,完成与该方法相同的功能。

gb.describe()
gb.agg(['count','mean','std','min',('25%',lambda x:x.quantile(0.25)),('50%','quantile'),('75%',lambda x:x.quantile(0.75)),'max'])

第四章 分组
由于传入的是序列,因此序列上的方法和属性都是可以在函数中使用的,只需保证返回值是标量即可。下面的例子是指,如果组的指标均值,超过该指标的总体均值,返回High,否则返回Low。
第四章 分组
【d】聚合结果重命名

如果想要对聚合结果的列名进行重命名,只需要将上述函数的位置改写成元组,元组的第一个元素为新的名字,第二个位置为原来的函数,包括聚合字符串和自定义函数,现举若干例子说明:
第四章 分组
另外需要注意,使用对一个或者多个列使用单个聚合的时候,重命名需要加方括号,否则就不知道是新的名字还是手误输错的内置函数字符串
第四章 分组

三、变换和过滤

1. 变换函数与transform方法

变换函数的返回值为同长度的序列,最常用的内置变换函数是累计函数: cumcount/cumsum/cumprod/cummax/cummin ,它们的使用方式和聚合函数类似,只不过完成的是组内累计操作。
第四章 分组
当用自定义变换时需要使用 transform 方法,被调用的自定义函数, 其传入值为数据源的序列 ,与 agg 的传入类型是一致的,其最后的返回结果是行列索引与数据源一致的 DataFrame 。

2.组索引与过滤

组过滤作为行过滤的推广,指的是如果对一个组的全体所在行进行统计的结果返回 True 则会被保留, False 则该组会被过滤,最后把所有未被过滤的组其对应的所在行拼接起来作为 DataFrame 返回。
在 groupby 对象中,定义了 filter 方法进行组的筛选,其中自定义函数的输入参数为数据源构成的 DataFrame 本身,在之前例子中定义的 groupby 对象中,传入的就是 df[[‘Height’, ‘Weight’]] ,因此所有表方法和属性都可以在自定义函数中相应地使用,同时只需保证自定义函数的返回为布尔值即可。

跨列分组

一般使用apply
参考
https://datawhalechina.github.io/joyful-pandas/build/html/%E7%9B%AE%E5%BD%95/ch4.html

上一篇:跟小白学Python数据分析——分组分析


下一篇:DataWhale & Pandas(四、分组)