Pandas GroupBy 详解2:深入理解与实践

Pandas GroupBy 详解:深入理解与实践

pandas 是 Python 数据分析的核心库之一,而 groupby() 则是 Pandas 中一个强大而灵活的工具。它帮助我们轻松地对数据进行分组和聚合,以便从数据中提取有价值的信息。本文将详细解释 groupby() 的使用细节,以及其他相关函数如何配合 groupby() 完成各种复杂的分析任务。

GroupBy 工作流程

使用 groupby() 进行数据分组的过程可以概括为 “分割-应用-组合” 的三步流程:

  1. 分割(Split):按指定的键(列)将数据分成不同的组。
  2. 应用(Apply):对每个组应用聚合函数、变换函数或其他自定义函数。
  3. 组合(Combine):将每组操作的结果合并成一个新的数据结构。

这种工作流程使得我们可以灵活地对每个组的数据进行操作并获取汇总信息。

基础示例

我们先通过一个简单的数据集来演示分组操作:

import pandas as pd

# 创建数据集
data = {
    '城市': ['北京', '上海', '广州', '北京', '广州', '上海', '北京'],
    '销售额': [100, 200, 150, 80, 120, 250, 90],
    '月份': ['一月', '一月', '一月', '二月', '二月', '二月', '三月']
}

df = pd.DataFrame(data)
print(df)

输出结果:

   城市   销售额  月份
0  北京  100  一月
1  上海  200  一月
2  广州  150  一月
3  北京   80  二月
4  广州  120  二月
5  上海  250  二月
6  北京   90  三月
使用 GroupBy 进行分组聚合

使用 groupby() 方法对数据按城市进行分组,然后使用 sum() 计算每个城市的总销售额:

grouped = df.groupby('城市')['销售额'].sum()
print(grouped)

输出结果:

城市
北京    270
广州    270
上海    450
Name: 销售额, dtype: int64

在这个例子中,我们首先使用 groupby('城市') 按照 城市 列对数据进行分组,接着使用 ['销售额'].sum() 对每个城市的 销售额 进行求和。

GroupBy 的细节:层级索引与多重索引

使用 groupby() 时,得到的结果往往包含多重索引。尤其在对多个列进行分组时,多重索引的结构会更加复杂。例如:

grouped_multi = df.groupby(['城市', '月份'])['销售额'].sum()
print(grouped_multi)

输出结果:

城市  月份
北京  一月    100
    二月     80
    三月     90
广州  一月    150
    二月    120
上海  一月    200
    二月    250
Name: 销售额, dtype: int64

这里得到的是一个具有多重索引的 Series,我们可以通过 reset_index() 方法将其转换回 DataFrame 格式:

reset_df = grouped_multi.reset_index()
print(reset_df)

输出结果:

    城市  月份  销售额
0   北京  一月  100
1   北京  二月   80
2   北京  三月   90
3   广州  一月  150
4   广州  二月  120
5   上海  一月  200
6   上海  二月  250
使用 transform 进行分组后的变换

transform() 方法可以在分组后对数据进行转换,并返回一个与原数据相同大小的结果。例如,我们想计算每个城市的平均销售额,并将结果作为新列添加到原数据中:

df['平均销售额'] = df.groupby('城市')['销售额'].transform('mean')
print(df)

输出结果:

   城市  销售额  月份   平均销售额
0  北京  100  一月   90.0
1  上海  200  一月  225.0
2  广州  150  一月  135.0
3  北京   80  二月   90.0
4  广州  120  二月  135.0
5  上海  250  二月  225.0
6  北京   90  三月   90.0
使用 apply 进行自定义分组处理

apply() 方法允许我们对每个组执行自定义的操作,具有极高的灵活性。例如,我们对每个城市的销售额进行标准化处理:

def standardize(group):
    return (group - group.mean()) / group.std()

df['标准化销售额'] = df.groupby('城市')['销售额'].apply(standardize)
print(df)

输出结果:

   城市  销售额  月份   平均销售额  标准化销售额
0  北京  100  一月   90.0  0.730297
1  上海  200  一月  225.0 -0.707107
2  广州  150  一月  135.0  0.707107
3  北京   80  二月   90.0 -1.095445
4  广州  120  二月  135.0 -0.707107
5  上海  250  二月  225.0  0.707107
6  北京   90  三月   90.0  0.365148

在这个例子中,我们对每个组使用 standardize() 函数来进行标准化处理,从而生成新的列。

分组后的过滤操作

有时候我们只需要保留符合特定条件的组,可以使用 filter() 方法。例如,我们只保留总销售额大于 300 的城市:

grouped_filter = df.groupby('城市').filter(lambda x: x['销售额'].sum() > 300)
print(grouped_filter)

输出结果:

   城市  销售额  月份   平均销售额  标准化销售额
1  上海  200  一月  225.0 -0.707107
2  广州  150  一月  135.0  0.707107
4  广州  120  二月  135.0 -0.707107
5  上海  250  二月  225.0  0.707107

通过 filter() 方法,我们只保留了销售额总和大于 300 的城市,删除了北京的数据。

分组聚合中的常用函数

groupby() 经常与各种聚合函数结合使用,以下是一些常见的聚合函数:

  • sum():求和
  • mean():均值
  • count():计数
  • max()min():最大值和最小值
  • median():中位数
  • std()var():标准差和方差

我们可以同时对多个列进行聚合操作,例如:

multi_agg = df.groupby('城市').agg({'销售额': ['sum', 'mean'], '月份': 'count'})
print(multi_agg)

输出结果:

      销售额          月份
       sum   mean count
城市                    
北京     270   90.0     3
广州     270  135.0     2
上海     450  225.0     2

在这个例子中,我们对 销售额 列进行了 summean 两种聚合操作,对 月份 列进行了 count 操作。

使用 apply 的注意事项与常见报错

在使用 apply() 进行分组操作时,有时会遇到与索引相关的错误。例如,如果我们尝试对每个城市的销售额进行标准化处理,并将结果赋值回原 DataFrame,如下所示:

def standardize(group):
    return (group - group.mean()) / group.std()

df['标准化销售额'] = df.groupby('城市')['销售额'].apply(standardize)

执行上面的代码时,可能会遇到如下错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
... 
TypeError: incompatible index of inserted column with frame index

这个错误通常是由于 apply() 之后返回的结果的索引与原 DataFrame 的索引不匹配引起的。当我们使用 apply() 进行分组操作时,返回的结果是按组处理的 Series,其索引可能与原始 DataFrame 不一致,导致赋值操作失败。

解决方案

为了解决这个问题,我们有两种方法:

  1. 使用 transform() 代替 apply()transform() 方法会返回与原始数据相同大小的结果,并且保持原 DataFrame 的索引结构一致,非常适合用于新增列的情况。
df['标准化销售额'] = df.groupby('城市')['销售额'].transform(standardize)
print(df)
  1. 如果必须使用 apply(),可以在返回的结果中重置索引,然后再赋值给原 DataFrame。例如:
standardized_sales = df.groupby('城市')['销售额'].apply(standardize).reset_index(level=0, drop=True)
df['标准化销售额'] = standardized_sales
print(df)

通过这种方式,我们确保 apply() 返回的结果与原 DataFrame 的索引匹配,从而避免类型不兼容的错误。

总结

本文详细介绍了 Pandas 中 groupby() 的使用细节,从基础的分组聚合操作到高级的分组变换、过滤和自定义操作。groupby() 是数据分析中非常重要的工具,它能够让我们灵活地对数据进行分组和处理。通过结合 transform()apply()filter() 等方法,我们可以极大地扩展分组操作的功能,以满足复杂的数据分析需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值