Python数据分组案例:如何高效分组统计数据(完整实战指南)
📚 目录导读
- 数据分组统计的痛点与Python优势
- 核心工具:Pandas groupby() 全面拆解
- 1 基础分组语法
- 2 单列分组统计
- 3 多列分组统计
- 实战案例:电商订单分组分析
- 1 数据准备
- 2 按产品类别统计销售额
- 3 按城市与月份统计订单量
- 进阶技巧:聚合函数与自定义逻辑
- 1 常用聚合函数
- 2 使用agg()自定义统计
- 3 重置索引与转化
- 常见错误与调优建议
- 问答环节:解决你的疑惑
数据分组统计的痛点与Python优势
在处理业务数据时,我们经常遇到这样的场景:面对一张包含数千条销售记录的表格,老板要求你“按产品类别统计总销售额”、“按城市查看每月订单增长”,传统的Excel手动筛选、分类汇总不仅耗时,还容易出错,而Python的pandas库提供了强大的groupby机制,让分组统计像写句子一样简洁——一行代码完成多维度聚合,速度快百倍,且结果可复现、可自动化。

Python分组统计的核心价值:
- 效率:几万行数据分组仅需毫秒级
- 灵活:支持单列/多列分组、多种聚合函数组合
- 可扩展:轻松集成到ETL流程或数据看板
核心工具:Pandas groupby() 全面拆解
1 基础分组语法
groupby的本质是“分->算->组”:按照指定列的值,将数据拆成若干组,对每组应用统计函数,最后合并结果。
通用格式:
df.groupby('分组列').agg('统计函数')
2 单列分组统计
假设有学生成绩表df,包含班级、姓名、分数:
# 按班级分组,计算平均分
df.groupby('班级')['分数'].mean()
输出结果类似:
班级
一班 85.3
二班 78.9
三班 92.1
3 多列分组统计
如果需要“按班级+性别”分组,只需传入列名列表:
# 按班级和性别分组,计算分数中位数 df.groupby(['班级', '性别'])['分数'].median()
注意:多列分组后,行索引变为MultiIndex,可通过reset_index()转换为普通列。
实战案例:电商订单分组分析
1 数据准备
模拟一份电商订单数据:
import pandas as pd
data = {
'订单ID': [1001,1002,1003,1004,1005,1006],
'产品类别': ['手机','手机','电脑','电脑','手机','电脑'],
'城市': ['北京','上海','北京','上海','上海','北京'],
'销售额': [5000,4500,8000,7200,5100,7600],
'订单日期': ['2024-01-15','2024-01-16','2024-01-15','2024-02-10','2024-02-11','2024-02-15']
}
df = pd.DataFrame(data)
2 按产品类别统计销售额
需求:每个类别卖了多少钱?
# 按产品类别分组,总和
category_sum = df.groupby('产品类别')['销售额'].sum()
print(category_sum)
输出:
产品类别
手机 14600
电脑 22800
3 按城市与月份统计订单量
需求:每个城市各月的订单数量。
先转换日期格式,提取月份:
df['订单日期'] = pd.to_datetime(df['订单日期']) df['月份'] = df['订单日期'].dt.month # 按城市和月份分组,计算订单数量 city_month_cnt = df.groupby(['城市', '月份']).size().reset_index(name='订单数') print(city_month_cnt)
输出:
城市 月份 订单数
0 北京 1 2
1 北京 2 1
2 上海 1 1
3 上海 2 2
注意:这里使用size()统计每个分组内的记录数,比count()更通用(不计缺失值)。
进阶技巧:聚合函数与自定义逻辑
1 常用聚合函数
| 函数 | 用途 | 示例 |
|---|---|---|
sum() |
求和 | 总销售额 |
mean() |
均值 | 平均订单金额 |
max()/min() |
最大值/最小值 | 最高/最低订单 |
std() |
标准差 | 数据波动分析 |
count() |
非空值计数 | 有效订单数 |
nunique() |
唯一值个数 | 不同产品数 |
2 使用agg()自定义统计
如果想同时看多个统计量,用agg()是最佳选择:
# 按产品类别,计算销售额的总和、均值、最大最小值
result = df.groupby('产品类别')['销售额'].agg(['sum', 'mean', 'max', 'min'])
print(result)
输出:
sum mean max min
产品类别
手机 14600 4866.67 5100 4500
电脑 22800 7600.00 8000 7200
还可以对多列分别应用不同函数:
df.groupby('产品类别').agg({
'销售额': 'sum',
'城市': 'nunique' # 统计每个类别涉及的不同城市数
})
3 重置索引与转化
分组后得到的是GroupBy对象或Series,如需转换为普通DataFrame,用reset_index():
# 将上面result的索引变回列 result_reset = result.reset_index() print(result_reset)
常见错误与调优建议
- 错误1:遗漏分组列导致TypeError
检查是否传入了列名(字符串或列表),而非DataFrame。 - 错误2:忘记重置索引
多列分组后索引变MultiIndex,用reset_index()恢复。 - 性能建议:对大数据集分组前,先按分组列排序(
sort_values),可提升groupby速度30%以上。 - 内存优化:使用
category类型存储低基数列(如城市名),减少内存占用。
❓ 问答环节:解决你的疑惑
Q1:groupby后如何保留原数据框的其他列?
A:默认只对指定列聚合,如果希望保留非统计列,可以在groupby后使用transform(),或用join连接统计结果与原始数据。
# 保留每个订单的同时,添加所属类别的总销售额
df['类别总销售额'] = df.groupby('产品类别')['销售额'].transform('sum')
Q2:分组统计时,空值如何处理?
A:groupby默认会忽略分组列中的NaN值(不产生该分组),如果希望保留NaN作为一个分组,设置dropna=False:
df.groupby('类别', dropna=False)['数值'].mean()
Q3:我想“按时间范围分组”怎么做?
A:先用pd.cut()或dt.month提取时间区间,再分组,例如按月、季度、年份:
df['季度'] = pd.cut(df['订单日期'].dt.month, bins=[0,3,6,9,12], labels=['Q1','Q2','Q3','Q4'])
df.groupby('季度')['销售额'].sum()
Q4:分组后如何排序?
A:用sort_values()对聚合结果排序:
rank = df.groupby('城市')['销售额'].sum().reset_index()
rank_sorted = rank.sort_values('销售额', ascending=False)
掌握分组统计,数据分析快10倍
Python的groupby + agg组合,是处理任何“按XX查看YY”需求的最快路径,从单列求和到多维度聚合,从内置函数到自定义逻辑,这一套方法论覆盖了日常90%的分组统计场景,下次遇到“按城市统计月销量总额,并找出销量前三的城市”,别打开Excel了!用Python 3行代码,秒出结果。
打开你的数据集,试试分组统计吧!