Python案例如何用Pandas做数据分组聚合

wen python案例 1

Python实战案例:如何用Pandas高效完成数据分组与聚合分析

文章导读目录

  • 为什么需要数据分组聚合?
  • Pandas分组聚合核心函数:groupby() 入门
  • 销售数据按“城市”分组求总销售额
  • 多级分组与自定义聚合函数(apply/agg)
  • 分组后保留原始数据的“复合操作”
  • 常见错误与性能优化技巧
  • SEO友好问答:新手最常问的5个问题
  • 总结与下一步学习建议

为什么需要数据分组聚合?

在数据分析工作中,我们经常遇到这样的需求:“按城市统计每月的总销售额”、“按部门计算员工的平均薪资”、“按产品类别找出库存最少的10个SKU”——这些操作本质都是 “分割-应用-组合” 的流程,Pandas中的groupby机制正是为此设计,它允许你:

Python案例如何用Pandas做数据分组聚合

  1. 根据某列(或多列)的值将数据分成多个组;
  2. 对每个组独立应用函数(求和、均值、计数、自定义逻辑);
  3. 将结果合并成一个新的DataFrame。

根据Seo技术社区的案例统计,90%的Pandas数据分析任务都会用到分组聚合,掌握这一技能,能让你处理10万行以上的数据集时,将代码从20行缩减到3行。


Pandas分组聚合核心函数:groupby() 入门

基本语法

df.groupby('列名')['待运算列'].聚合函数()
  • groupby('列名'):定义分组依据(可以是字符串或列表);
  • ['待运算列']:指定要进行聚合计算的列(可选,如果省略则对所有数字列操作);
  • .sum() / .mean() / .count() / .agg():聚合方式。

关键差异:.agg() vs .apply()

  • .agg():专注预定义聚合(sum, mean, np.std等),速度快,且对多列可指定不同函数;
  • .apply():更灵活,可传入自定义函数操作整个分组DataFrame,但性能略低。

销售数据按“城市”分组求总销售额

场景

有一份销售数据表(sales.csv),包含 城市销售员产品销售额日期 等字段,需要按城市汇总总销售额。

实现代码

import pandas as pd
# 读取数据
df = pd.read_csv('sales.csv')
# 分组聚合:按城市,对销售额求和
city_sales = df.groupby('城市')['销售额'].sum()
print(city_sales)

实际输出示例

城市
上海    125000
北京    98000
广州    72000
Name: 销售额, dtype: int64

拓展:同时查看多个聚合指标

city_stats = df.groupby('城市')['销售额'].agg(['sum', 'mean', 'count'])
print(city_stats)

此时会得到每个城市的总销售额、平均单笔销售额和订单数量——这是企业销售周报的常见统计维度。


多级分组与自定义聚合函数

需求

需要同时按 城市季度 分组,并且计算每个组的加权平均利润率(假设有 销售额利润 两列)。

多级分组

# 按两个列分组
grouped = df.groupby(['城市', '季度'])
# 多级聚合
result = grouped[['销售额', '利润']].sum()

此时索引成了MultiIndex(城市、季度),可以通过 .loc['上海':'北京']xs() 切片访问。

自定义聚合函数(使用lambdadef

# 自定义加权平均(假设利润率 = 利润/销售额)
def weighted_margin(group):
    return group['利润'].sum() / group['销售额'].sum()
margin_result = df.groupby('城市').apply(weighted_margin)
margin_result.name = '加权利润率'

注意:apply返回的是Series,适用于每个分组返回单个值的情形,如果需要按组处理后再拼接回原数据,使用.transform.filter


分组后保留原始数据的“复合操作”

有时候我们不希望仅仅得到一个汇总表,而是想保留原始行,同时增加分组统计列(给每一行标记该产品类别的平均价格)。

使用transform

# 计算每个产品类别下,该行的价格与类别平均价的差值
df['类别平均价'] = df.groupby('产品类别')['价格'].transform('mean')
df['价格差异'] = df['价格'] - df['类别平均价']

transform不会减少行数,只是将聚合结果广播回每一行——这在做异常值检测相对排名时非常有用。


常见错误与性能优化技巧

容易踩的坑

  1. 忘记.reset_index()groupby默认以分组列为索引,如果后续需要列名索引,记得调用.reset_index()
  2. 多级GroupBy后直接赋值df.groupby('A')['B'].sum() = something会报错,必须通过.transform实现;
  3. 数据中存在NaN:分组键如果有NaN,该组会被自动忽略,可先df.dropna(subset=['分组列'])

性能提升小贴士

  • 尽量使用.agg()而非.apply(),尤其是大数据集;
  • 对groupby的列先排序(sort=True),能减少分组时的计算开销;
  • 如果只需要部分列聚合,显式指定['销售额']而非整个DataFrame。

SEO友好问答:新手最常问的5个问题

Q1:groupbypivot_table有什么区别?
A:pivot_table底层也依赖groupby,但会自动生成行、列索引和数据透视格式,更美观;而groupby更灵活,适合编程处理。

Q2:如何对分组后的结果进行排序?
A:在groupby后接.agg(...).sort_values('列名', ascending=False)即可。

Q3:为什么我的groupby返回的是Series而不是DataFrame?
A:当你用['某列']指定单列后,聚合会返回Series,如果需要DataFrame,用两层方括号:[['某列']]

Q4:可以同时对字符串列和数值列分组吗?
A:可以,字符串列分组时,相同内容的行被划分为一组,数值列则分桶(需要先通过pd.cutpd.qcut分箱)。

Q5:多列groupby后,如何选择某个组?
A:使用.get_group(('组值1', '组值2'))方法,例如grouped.get_group(('上海', 'Q1'))


总结与下一步学习建议

通过以上案例,你已经掌握了Pandas分组聚合的核心场景:单列/多列求和、自定义指标计算、数据转换保留(transform)、以及性能避坑。实际工作中,80%的数据看板指标都可以通过组合.groupby() + .agg()来完成

建议你下一步:

  1. 尝试在真实数据集(如Kaggle的Titanic或零售销售)上练习多级分组和聚合;
  2. 阅读Pandas官方文档中关于.resample()(时间序列分组)的内容;
  3. 学习如何使用pd.Grouper处理更复杂的分组逻辑(如按周分组、按自定义区间分组)。

数据分析的本质是“告别手动,用代码让机器自动分身做事”——Pandas的groupby正是你手中最锋利的刀。

抱歉,评论功能暂时关闭!