Pandas分组统计

前言

在日常的数据分析中,经常需要将数据根据某个(多个)字段划分为不同的群体(group)进行分析,如电商领域将全国的总销售额根据省份进行划分,分析各省销售额的变化情况,社交领域将用户根据画像(性别、年龄)进行细分,研究用户的使用情况和偏好等,在Pandas中,上述的数据处理操作主要运用groupby完成。

如无特殊说明,本章所使用数据为 尿检结果.xls

https://cdn.jsdelivr.net/gh/wefantasy/FileCloud/img/20200814220628.png
尿检结果

介绍

Pandas分组统计函数原型为:

1
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=<object object>, observed=False, dropna=True)

其中各参数参数含义如下:

参数 介绍
by 分组依据
axis 按行分组还是按列分组
as_index 控制聚合输出是否以组标签为索引值
level 如果是多级索引,则按一个或多个特定级别分组
sort 组间排序,关闭可以获得更好的性能
group_keys 当调用apply时,将组关键字添加到索引以识别片段
dropna 是否删除Nan值

使用

分组

  1. 分组 在Pandas中,实现分组操作的代码很简单,在此将上面的数据集按照“送检科室”字段进行划分:
1
2
data = pd.read_excel(r"C:\Users\Fantasy\Desktop\尿检结果.xls", header=[0])
result = data.groupby(by="送检科室")

将上述代码运行后,会得到一个DataFrameGroupBy对象(result),是一个内存地址,可以使用result.groups命令查看分组情况。为了利于观察,这里可以把group转换成list的形式来看一看:

https://cdn.jsdelivr.net/gh/wefantasy/FileCloud/img/20200822233148.png
groupby结果

转换成列表的形式后,可以看到,结果是由元组组成的列表,每个元组中,第一个元素是组别关键字,第二个元素的是对应组别下的DataFrame数据。总的来说,groupby的过程就是将原有的DataFrame按照groupby的字段(这里是“送检科室”),划分为若干个分组DataFrame,被分为多少个组就有多少个分组DataFrame。所以说,在groupby之后的一系列操作(如agg、apply等),均是基于子DataFrame的操作。

  1. 遍历分组 可以直接使用Python的for-in语句遍历分组结果1
1
2
3
for name,group in result:
    print (name)
    print (group_data)
  1. 选择分组 使用get_group()方法,可以选择一个组。
1
result.get_group('方便门诊')

聚合

聚合函数为每个组返回单个聚合值,当创建了分组(groupby)对象,就可以对分组数据执行多个聚合操作,主要的聚合函数有以下三种:

agg

agg方法是groupby聚合的常用方法,主要有min、max、sum、mean、median、std、var、count等统计方法,其常用有以下几种场景:

1
2
3
4
result.agg('mean')  # 获取每组平均值(另写 result.mean())
result.agg(['std','var'])  # 获取每组标准差和方差
result.agg({'白细胞计数':'mean','红细胞计数':'sum'})    # 白细胞计数获取均值,红细胞计数获取和
result.agg({'白细胞计数':'mean','红细胞计数':'sum'}).sort_values(by='白细胞计数')  # 白细胞计数获取均值,红细胞计数获取和,结果按白细胞均值排序

transform

有时候我们需要将聚合结果与原数据进行关联运算,这时候便要使用transform,它的聚合结果的索引大小与被分组的索引相同的对象,以至于很容易与原DataFrame数据进行二次运算。2 例:获取同一分组中血小板计数在本组均值的偏离情况

1
data['白细胞计数均差'] = data['白细胞计数'] - result['白细胞计数'].transform('mean')

https://cdn.jsdelivr.net/gh/wefantasy/FileCloud/img/20200823223057.png
白细胞计数均差

apply

apply相比agg和transform而言更加灵活,能够传入任意自定义的函数,实现复杂的数据操作。3以下代码用于获取每组中血红蛋白最大的数据:

1
2
3
4
def get_max_xuehongdanbai(x):
    df = x.sort_values(by = '血红蛋白',ascending=True)
    return df.iloc[-1,:]
result.apply(get_max_xuehongdanbai)
技巧
apply与agg的主要区别之一是,apply处理的对象是一个个的类如DataFrame的数据表,然而agg则每次只传入一列。

filter

filter()函数用于过滤数据,它会根据定义的标准过滤数据并返回数据的子集。 例:过滤出均值大于7的分组

1
result.filter(lambda x:x['白细胞计数'].mean() > 7)

参考


  1. 奔跑的乌班. pandas分组统计 - groupby功能. CSDN. [2019-01-05] ↩︎

  2. 大邓. 如何理解pandas中的transform函数. 知乎. [2019-10-12] ↩︎

  3. Python读财. Pandas数据分析教程——超好用的Groupby用法详解. 简书. [2020-01-06] ↩︎