数据分析库pandas入门 7——分组、聚合、pivot_table数据透视表、crosstab数据交叉表
本篇介绍数据分组聚合以及 pivot_table 和 crosstab 函数,这些都是数据处理、分组统计非常常用的方法。
Pandas库使用入门7——数据分组聚合
在前几篇关于 pandas 的文章中,笔者分别介绍了:
- pandas 的基本数据结构、数据对象的创建和查看
- pandas 数据的数值运算、统计和排序
- 对 DataFrame 类型数据的索引和轴进行的一些操作
- 添加数据与合并数据
- 删除数据、数据去重、缺失值处理
- 几个重要的方法/函数:apply/applymap/map、cut/qcut、melt、get_dummies
在上一篇文章中,笔者介绍了几个重要且常用的方法/函数,这些函数连同 numpy 的部分通用函数常常会在本篇介绍的数据分组聚合中使用。所谓分组聚合,就是对原始数据按照某(些)属性/列的值进行分类,值相同的放同一组,然后对各组(某些属性/列)进行某种函数处理(比如统计计算),最后对结果进行综合,是数据处理、分组统计的非常常用的方法。这个过程可以分为:拆分(根据一或多个键将数据拆分为多组)、应用(根据提供的一个函数应用到这些分组上)、合并(将函数的执行结果合并到最终结果中)。
分组
分组的过程就是上面所述的拆分,使用 groupby 函数。该函数返回一个 DataFrameGroupBy / SeriesGroupBy 对象,它是可迭代的,可以用一个(或一组)列名对其索引。
df.groupby(by, axis=0, level, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)
by:一个 mapping function / list of function / 字典 / 序列 / 元组 / list of column name,指定了分组数据。
axis:为0/‘index’,表示沿着0轴分组;为1/‘columns’,表示沿着1轴。
level:如果 axis 是个 MultiIndex,则在指定级别上的索引来分组。
as_index:如果为 True,则将 group label 作为输出的 index。如果为 False,则分组的 key 作为一列,而不是作为 index。
sort:如果为True,则对分组的键进行排序。
group_keys:如果为True,且调用了函数来决定分组,则添加分组键来区分不同的数据。
squeeze:如果为True,则尽可能缩减结果的类型。
示例如下:
import numpy as np
import pandas as pd
df = pd.DataFrame(data = [(1, 145.5, 5.0, 33, 'M', 78.5),
(2, 167.2, 5.4, 45, 'M', 92),
(3, 124.1, 5.2, 23, 'F', 66.5),
(1, 144.5, 5.1, 33, 'M', 80),
(2, 133.2, 5.7, 54, 'F', 82),
(5, 129.2, 5.3, 42, 'M', 69)], columns=['gid','weight','height','age','gender','score'])
dfg1 = df.groupby('gid') # 按照 'gid' 分组
dfg2 = df.groupby(by=['gid','gender']) # 按照 'gid' 和 'gender' 分组
dfg2.groups # 查看分组对象的 groups 字典属性,即:各个分组及其对应的数据行
for i in dfg1: # 遍历分组对象查看各分组具体数据
print(i)
sg1 = df.groupby('gid')['age'] # 按照'gid'分组并取'age'列,返回一个 SeriesGroupBy 对象
sg2 = df.groupby('gender', as_index=False) # 按照'gender'分组且不把'gender'作为行索引
dfg3 = df.groupby(pd.cut(df['score'], [0,60,70,85,100])) # 按照'score'指定分段进行分组
聚合
聚合的过程就是分组之后的应用和合并,GroupBy 对象有很多聚合函数可供使用,如一般的统计函数max()、min()、count()、sum()、mean()、median()、std()等等。还可以使用自定义聚合函数,只需要将其传入.aggregate(func, *args, **kwargs)或者.agg()方法即可(其中func接受一维数组,返回一个标量值)。apply 是另一个最一般化的分组级运算。它将待处理的对象拆分成多个片段,然后对各个片段调用传入的函数,最后尝试将各个片段组合到一起。
示例如下:
dfg1.count() # 对dfg1各组所有列进行计数
dfg1.value_counts() # 统计dfg1分组数量并降序排序
dfg2.mean() # 对dfg2各组所有列取均值
dfg3.score.max() # 对dfg3分组中'score'列取最大值
dfg1['score'].mean() # 对dfg1各组取'score'列并计算均值
dfg1['score'].agg(lambda x:x.max()-x.min()) # 按'gid'分组后取'score'列并计算最大值与最小值之差
df.groupby('gender')['score'].agg(['mean','var']) # 按'gender'列分组后取'score'列并计算均值和方差
dfg2.agg({'age':'mean','score':'sum'}) # 对dfg2分组取'age'列的均值和'score'列的总和
dfg1.apply(lambda x:type(x)) # func返回一个标量,即分组类型
dfg1.apply(lambda x:x.age) # func返回一个Series,即分组的'age'列
pivot_table 数据透视表
透视表 pivot_table 是一种数据汇总工具,它根据一或多个键对数据进行聚合,并根据行和列上的分组键将数据分配到各个单元格中。当然,这也可以通过上述 groupby 分组聚合以及索引变换来实现,但用 pivot_table 更方便简洁。该方法既是DataFrame 对象方法,也是 pandas 内置函数,功能是一样的:
pandas.pivot_table(data, values, index, columns, aggfunc='mean', fill_value, margins=False, dropna=True, margins_name='All', observed=False, sort=True)
data:需要进行数据透视的 DataFrame 对象。
values:指定哪些列将被聚合,默认所有的数值列。
index:一个index label / Grouper / 数组 / 这些类型的一个列表,指定关于分组的列名或者其他分组键,出现在结果透视表的行。
columns:一个column label / Grouper / 数组 / 这些类型的一个列表,指定关于分组的列名或者其他分组键,出现在结果透视表的列。
aggfunc:聚合函数或函数列表,默认为 numpy.mean。如果为函数列表,则结果中有多级索引,函数名是最外层索引名。
fill_value:一个标量,用于替换 NaN。
margins:如果为True,则添加行/列的总计。
dropna:如果为True,则结果不包含所有元素都是 NaN 的列。
示例如下:
# 按'gender'统计'weight'的均值
pd.pivot_table(df, values='weight', index='gender', aggfunc='mean')
# 按'gid'统计'score'的总和
pd.pivot_table(df, values='score', columns='gid', aggfunc='sum')
# 按'gender'(行)和'gid'(列)分组统计各组'score'的总和
pd.pivot_table(df, index='gender', values='score', columns='gid', aggfunc='sum')
crosstab 数据交叉表
数据交叉表 crosstab 是一种用于计算分组频率的特殊透视表,这可以使用上述 pivot_table 函数实现,但是直接使用 crosstab 更方便:
pandas.crosstab(index, columns, values, rownames, colnames, aggfunc, margins=False, dropna=True, normalize=False)
index:一个array-like、Series或者前两种的列表。指定行的计算频数的数据。
columns:一个array-like、Series或者前两种的列表。指定列的计算频数的数据。
values:用于聚合的数据。如果指定了 values,则必须提供aggfunc。
aggfunc:聚合函数。如果出现了aggfunc,则必须提供values。
rownames:一个序列。如果非空,则必须和结果的row index的level数量相等
colnames:一个序列。如果非空,则必须和结果的column index的level数量相等
margins:如果为True,则添加行/列的总计。
dropna:如果为True,则结果不包含这样的列:该列所有元素都是NaN
normalize:一个布尔值、字符串(‘all’/‘index’/‘columns’)、或者整数0/1。指定是否进行归一化处理(归一化为频率),否则就是频数。
示例如下:
# 统计不同'gender'不同'gid'的分组中样本数量
pd.crosstab(index=df['gender'], columns=df['gid'])
# 统计不同'gender'不同'gid'的分组中各组的'score'均值
pd.crosstab(index=df['gender'], columns=df['gid'], values=df['score'], aggfunc='mean')
以上。
更多推荐
所有评论(0)