Pandas中数据分组进阶以及数据透视表

一、数据分组步骤

1.用groupby进行分组

2.对分组数据进行聚合、转换和过滤

3.应用自定义函数处理分组之后的数据

二、分组基础

概念

类似于SQL中的GROUP BY 的操作,按照字段进行分组,对每组数据进行进一步处理并返回单个值的操作称为聚合。

示例

python 复制代码
# 加载数据
df = pd.read_csv('data/gapminder.tsv', sep='\t')
# 按year分组,计算lifeExp的平均值
df.groupby('year').lifeExp.mean()

上述操作等价于手动筛选每一年的数据并计算平均值,groupby自动完成这一重复过程并整合结果。

三:聚合

1.内置聚合方法:

说明 Pandas 方法 Numpy 函数
频率统计(不含 NaN) count np.count_nonzero
频率统计(含 NaN) size -
求平均值 mean np.mean
标准差 std np.std
最小值 min np.min
分位数 quantile() np.percentile()
最大值 max np.max
求和 sum np.sum
方差 var np.var
综合统计 describe -
返回第一行 first -
返回最后一行 last -
返回第 N 行 nth -

示例:df.groupby('continent').lifeExp.describe()返回各州寿命的多项统计量

2.聚合函数使用

可使用agg或者aggregate(两者效果一致)调用函数,支持numpy函数、自定义函数。

自定义函数实例:

python 复制代码
def my_mean(values):
    n = len(values)
    sum = 0
    for value in values:
        sum += value
    return sum / n
# 调用
df.groupby('year').lifeExp.agg(my_mean)

自定义多参数函数实例(计算与全局平均值的差值):

python 复制代码
def my_mean_diff(values, diff_value):
    n = len(values)
    sum = 0
    for value in values:
        sum += value
    mean = sum / n
    return mean - diff_value
global_mean = df.lifeExp.mean()
df.groupby('year').lifeExp.agg(my_mean_diff, diff_value=global_mean)

3.多函数与多字段聚合:

传入函数列表同时计算多个聚合结果:

python 复制代码
result = df.groupby('year')['lifeExp'].agg(['count', 'mean', 'std'])

传入字典对不同字段使用不同聚合方式:

python 复制代码
print(df.groupby('year').agg({
    'lifeExp':'mean',
    'pop':'max',
    'gdpPercap':'max'
}).rename(columns={'pop':'pop_max','gdpPercap':'gdp_percap_max','life':'life_max'}).reset_index())

四、转换操作

1.特点

将数据传递给函数进行转换,不减少数据量(与聚合返回单个值不同)。

2.自定义函数替换示例:

python 复制代码
def my_zscore(x):
    return (x - x.mean()) / x.std()
# 按年分组计算z分数
df.groupby('year').lifeExp.transform(my_zscore)

3.分组来填充缺失值:

python 复制代码
# 构建含缺失值的数据
tips_10 = pd.read_csv('data/tips.csv').sample(10, random_state=42)
tips_10.loc[np.random.permutation(tips_10.index)[:4], 'total_bill'] = np.NaN
# 定义填充函数
def fill_na_mean(x):
    avg = x.mean()
    return x.fillna(avg)
# 按性别分组填充
total_bill_group_mean = tips_10.groupby('sex').total_bill.transform(fill_na_mean)

五、过滤操作

通过filter方法传入返回布尔值的函数,过滤返回False的数据。

示例(过滤用餐人数较少的组):

python 复制代码
tips = pd.read_csv('data/tips.csv')
# 过滤掉人数计数≤30的组
tips_filtered = tips.groupby('size').filter(lambda x: x['size'].count() > 30)

六、DataFrameGroupBy对象

1.创建与属性

在调用groupby后得到DataFrameGroupby对象,如grouped = tips_10.groupby('sex')。

通过groups属性查看分组的索引信息,grouped.groups返回各组对应的原始数据行索引。

2.分组计算与选择

直接在对象上进行聚合、转换等操作,如grouped.mean(numeric_only = True)计算数值列平均值。

通过get_group选择特定分组,如female = grouped.get_group('Female')。

3.遍历分组

可通过for循坏遍历分组,每个分组为元组(包含组名和对应DataFrame):

python 复制代码
for sex_group in grouped:
    print(sex_group[0])  # 组名(如'Female')
    print(sex_group[1])  # 组数据(DataFrame)

4.多字段分组:

传入多个字段进行分组,如group_avg = tips_10.groupby(['sex','time']).mean(),返回MultiIndex结果。

可通过reset_index()或as_index = False将结果转为普通DataDrame:

python 复制代码
group_avg.reset_index()
# 或分组时设置
tips_10.groupby(['sex', 'time'], as_index=False).mean()

七、分组总结

1.分组是数据分析的重要操作,可从不同角度观察数据。

2.分组后得到的DataFrameGroupBy对象支持聚合、转换、过滤操作。

3.处理分组数据可使用内置函数或自定义函数,支持单字段和多字段分组,多字段分组结果可转为普通 DataFrame。

八、数据透视表

1.概念

数据透视表是一种交互式的数据汇总工具,能够对数据进行灵活的分组、聚合和分析。它的核心特点是可以动态调整数据的展示结构,通过重新排列行、列和统计指标,从多个维度挖掘数据规律。

通俗理解:类似与"数据魔方",可以根据需求自由旋转(调整行 / 列维度),快速切换分析视角,无需重复编写复杂的分组代码。

与普通表格的区别:普通表格是数据的原始呈现,而透视表是对原始数据的汇总计算结果(如求和、平均值等),且结构可动态调整。

2.核心作用

1.多维度汇总

将复杂数据按多个维度(如时间、类别、地区等)拆分并汇总,清晰展示各维度交叉下的统计结果。

2.灵活分析

无需修改原始数据,通过拖拽或参数调整即可切换分析维度(如从 "按地区统计" 改为 "按地区 + 时间统计")。

3.高效计算

内置多种聚合函数(求和、均值、计数等),自动完成批量计算,避免手动编写分组聚合代码。

4.动态更新

当原始数据发生变化时,可一键更新透视表结果,保证分析的时效性。

3.核心函数(pivot_table函数)

核心参数如下:

参数名 作用说明 示例
data 输入的原始 DataFrame(仅pandas.pivot_table需要,DataFrame.pivot_table无需) data=df
index 作为行索引的字段(分组的行维度) index='category'(按类别分行)
columns 作为列索引的字段(分组的列维度) columns='year'(按年份分列)
values 需要聚合计算的字段(被统计的指标) values='sales'(统计销售额)
aggfunc 聚合函数(默认是mean,可自定义) aggfunc='sum'(求和)

4.基本使用示例

1.数据显示

python 复制代码
import pandas as pd
data = {
    '地区': ['华东', '华东', '华北', '华北', '华东', '华北'],
    '年份': [2022, 2023, 2022, 2023, 2023, 2022],
    '销售额': [100, 120, 80, 90, 130, 70],
    '利润': [20, 25, 15, 18, 28, 14]
}
df = pd.DataFrame(data)

2.基本透视表:按照地区和年份统计销售额总和

python 复制代码
# 行索引为地区,列索引为年份,统计销售额的总和
pivot = df.pivot_table(
    index='地区',    # 行维度:按地区分组
    columns='年份',  # 列维度:按年份分组
    values='销售额', # 统计指标:销售额
    aggfunc='sum'    # 聚合方式:求和
)
print(pivot)
python 复制代码
年份   2022  2023
地区            
华东   100   250  # 华东2023年销售额=120+130
华北    150   90  # 华北2022年销售额=80+70

3.多指标与多聚合函数

python 复制代码
# 同时统计销售额和利润,分别计算总和与平均值
pivot = df.pivot_table(
    index='地区',
    columns='年份',
    values=['销售额', '利润'],  # 多个指标
    aggfunc={'销售额': 'sum', '利润': 'mean'}  # 不同指标用不同聚合函数
)

这里通过字典来指定aggfunc实现对不同字段的差异化计算。

4.处理缺失值

可通过fill_value参数填充

python 复制代码
pivot = df.pivot_table(
    index='地区',
    columns='年份',
    values='销售额',
    aggfunc='sum',
    fill_value=0  # 用0填充缺失值
)

5.取消索引层级(转为普通DataFrame)

可通过margins和reset_index调整:

python 复制代码
pivot = df.pivot_table(
    index='地区',
    columns='年份',
    values='销售额',
    aggfunc='sum',
    margins=True,  # 添加总计行/列
    margins_name='总计'  # 总计的名称
).reset_index()  # 将行索引转为普通列

6.应用场景

1.业务数据分析:如按地区、时间、产品类别分析销量 / 利润,快速定位高贡献区域或产品。

2.用户行为分析:按用户群体、行为类型、时间统计活跃度,识别核心用户特征。

3.实验数据汇总:按实验组、变量类型统计实验结果的均值 / 标准差,对比不同实验条件的效果。

4.报表自动化:生成动态可调整的汇总报表,替代重复的groupby代码。

7.其他

1.聚合函数的选择:根据数据类型选择合适的函数(数值型用sum/mean,类别型用count)。

2.维度控制:维度过多(行 / 列字段过多)会导致透视表臃肿,建议优先保留核心分析维度。

3.与groupby的区别:groupby适合固定维度的分组计算,而透视表更擅长动态调整维度可视化展示,两者可结合使用(如先用groupby预处理数据,再用透视表汇总)。