Pandas 分组与聚合分析(groupby)
在数据分析中,我们常常需要对数据进行分类统计、汇总计算或分组比较,例如:按地区计算销售额、按部门求平均工资、或根据多条件筛选群体特征等。
在 Pandas 中,groupby
是实现这些操作的核心工具。它能够高效地将数据按一个或多个条件分组,再进行聚合、变换或筛选,是探索性分析与报表生成中不可或缺的利器。
1. 分组统计基础
groupby
可以将数据集按指定列分组,再对每个分组应用统计或聚合操作。下面通过一个示例来演示它的基本用法。
import pandas as pd
data = {
"姓名": ["张三", "李四", "王五", "赵六", "孙七", "周八"],
"城市": ["北京", "上海", "北京", "深圳", "上海", "北京"],
"销售额": [100, 150, 200, 130, 160, 180],
"年龄": [23, 34, 29, 40, 34, 28]
}
df = pd.DataFrame(data)
print(df)
姓名 城市 销售额 年龄
0 张三 北京 100 23
1 李四 上海 150 34
2 王五 北京 200 29
3 赵六 深圳 130 40
4 孙七 上海 160 34
5 周八 北京 180 28
如果想按城市统计总销售额,只需一行代码:
# 按城市分组,计算销售额总和
city_sales = df.groupby('城市')['销售额'].sum()
print(city_sales)
城市
上海 310
北京 480
深圳 130
Name: 销售额, dtype: int64
这一步中,groupby('城市')
将数据按城市划分为三个组,然后对每组的“销售额”求和。
2. 使用聚合函数(agg / apply)
2.1 使用 agg
进行多种统计
在实际分析中,我们往往需要对每个分组计算多个指标,如求和、平均值和最大值等。此时可以使用 agg()
方法,它允许同时执行多种聚合运算。
city_stats = df.groupby('城市')['销售额'].agg(['sum', 'mean', 'max'])
print(city_stats)
sum mean max
城市
上海 310 155.0 160
北京 480 160.0 200
深圳 130 130.0 130
2.2 使用自定义函数 apply
agg()
的优势在于可读性强,适合快速生成多指标报表。如果需要更灵活的自定义计算逻辑,可以使用 apply()
。
例如,下面定义一个函数,用于计算每个城市销售额的范围(最大值减最小值):
# 自定义函数:销售额范围
def sales_range(x):
return x.max() - x.min()
city_range = df.groupby('城市')['销售额'].apply(sales_range)
print(city_range)
城市
上海 10
北京 100
深圳 0
Name: 销售额, dtype: int64
这样,我们就能轻松扩展分组逻辑,用自定义函数表达复杂的业务规则。
3. 多重分组与层次化索引
3.1 多列分组
在许多场景中,分组往往需要考虑多个维度,例如“按城市与年龄同时分组”。Pandas 支持这种多级分组,并会自动生成层次化索引。
multi_group = df.groupby(['城市', '年龄'])['销售额'].sum()
print(multi_group)
城市 年龄
上海 34 310
北京 23 100
28 180
29 200
深圳 40 130
Name: 销售额, dtype: int64
可以看到,结果是一个具有两级索引的 Series。
3.2 重置索引查看扁平化表格
如果想将其转换为普通表格结构,使用 reset_index()
即可:
multi_group_reset = multi_group.reset_index()
print(multi_group_reset)
城市 年龄 销售额
0 上海 34 310
1 北京 23 100
2 北京 28 180
3 北京 29 200
4 深圳 40 130
多重分组在业务数据分析中极为常见,例如计算“不同城市各年龄段销售表现”或“不同部门各季度指标”等。
4. 分组筛选与变换
groupby
还可以对分组后的数据进行筛选和变换操作,使分析更加灵活。
4.1 分组筛选
例如,若我们只关心销售额总和大于 200 的城市组,可以使用 filter()
:
# 筛选销售额总和大于200的城市组
group_filter = df.groupby('城市').filter(lambda x: x['销售额'].sum() > 200)
print(group_filter)
姓名 城市 销售额 年龄
0 张三 北京 100 23
1 李四 上海 150 34
2 王五 北京 200 29
4 孙七 上海 160 34
5 周八 北京 180 28
4.2 分组变换
transform()
则可对分组结果进行数值变换,并将结果返回到原 DataFrame。例如,可以计算每个城市的销售额与该城市平均销售额的差异:
# 将每个城市的销售额减去该城市平均销售额
df['销售额差值'] = df.groupby('城市')['销售额'].transform(lambda x: x - x.mean())
print(df)
姓名 城市 销售额 年龄 销售额差值
0 张三 北京 100 23 -60.0
1 李四 上海 150 34 -5.0
2 王五 北京 200 29 40.0
3 赵六 深圳 130 40 0.0
4 孙七 上海 160 34 5.0
5 周八 北京 180 28 20.0
通过 transform()
,我们能够在分组的基础上生成新特征,适合偏差分析、标准化处理或分组归一化等任务。
5. 小结
groupby
是 Pandas 中最强大、最常用的分析工具之一。它不仅能实现按类别或条件分组的聚合统计,还能灵活支持多重分组、自定义函数、筛选与变换等多样化操作。熟练掌握它,能大幅提升处理大规模数据的效率,为后续的数据建模、趋势分析和可视化打下坚实基础。