Python案例如何用Pandas做数据分组统计量

wen python案例 1

Python案例详解如何用Pandas做数据分组统计量

📚 目录导读

  1. 引言:为什么数据分组统计是数据分析的核心?
  2. Pandas分组统计基础:groupby() 的工作原理
  3. 实战案例一:销售数据按类别统计总额与均值
  4. 实战案例二:多级分组与聚合函数组合应用
  5. 实战案例三:自定义聚合函数与分组后变换
  6. 常见问题与避坑指南(Q&A)
  7. 掌握分组统计的三大心法

引言:为什么数据分组统计是数据分析的核心?

在数据分析的日常工作中,面对动辄上万行、数百列的表格数据,我们常常需要回答这类问题:“不同产品类别的平均销售额是多少?” 或者 “每个地区的订单数量分布如何?”,这类“按某个维度分组,然后计算统计量”的操作,正是分组统计(GroupBy) 的用武之地。

Python案例如何用Pandas做数据分组统计量

Pandas作为Python数据分析的“瑞士军刀”,其groupby()功能结合聚合函数(如sum(), mean(), count()),可以在几行代码内完成传统Excel需要繁琐透视表操作的任务,本文将通过三个完整的Python案例,手把手教你如何用Pandas实现高效的数据分组统计,并附上搜索引擎优化(SEO)友好的问答环节,帮你避开常见陷阱。

适用人群:有Python基础但刚接触Pandas的数据分析新手,以及希望提升数据预处理效率的从业者。


Pandas分组统计基础:groupby() 的工作原理

在深入案例前,我们先理解核心机制,Pandas的groupby()生成一个GroupBy对象,它本身并不立即计算,而是懒加载——只有当你调用聚合函数(如.sum().mean())时,才会执行计算并返回结果。

基本流程三步骤

  • 拆分(Split):根据指定列(或多个列)将DataFrame拆分为多个组。
  • 应用(Apply):对每个组独立应用一个函数(聚合、转换或过滤)。
  • 组合(Combine):将各组结果合并到一个DataFrame或Series中。
import pandas as pd
# 示例数据
df = pd.DataFrame({
    '类别': ['A', 'A', 'B', 'B', 'A'],
    '金额': [100, 150, 200, 250, 300]
})
# 第一步:按'类别'分组,第二步:计算每组金额总和
result = df.groupby('类别')['金额'].sum()

输出结果会是一个带有类别索引的Series,包含了每个组的统计量。


实战案例一:销售数据按类别统计总额与均值

场景描述

假设你是一家电商公司的数据分析师,有一张包含订单ID产品类别销售额利润的表格,老板想知道每个产品类别的总销售额平均利润

完整代码与解析

import pandas as pd
# 构造模拟数据
data = {
    '订单ID': [101, 102, 103, 104, 105],
    '类别': ['电子产品', '服饰', '电子产品', '食品', '服饰'],
    '销售额': [5000, 1200, 8000, 450, 2500],
    '利润': [1000, 300, 1500, 100, 500]
}
df_sales = pd.DataFrame(data)
# 按类别分组,同时计算销售额总和与利润均值
grouped = df_sales.groupby('类别').agg(
    总销售额=('销售额', 'sum'),
    平均利润=('利润', 'mean')
).reset_index()  # 将分组键从索引变为普通列
print(grouped)

输出结果

   类别  总销售额  平均利润
0  服饰    3700   400.0
1  食品     450   100.0
2  电子产品  13000  1250.0

关键点

  • agg() 函数可以同时指定多个聚合方式,传入一个字典或元组列表。
  • reset_index() 将分组列还原为普通列,便于后续处理或导出。

实战案例二:多级分组与聚合函数组合应用

场景描述

数据更加复杂时,我们需要按多个维度分组,某连锁超市希望按城市门店类型(如“旗舰店”、“标准店”)两个维度,统计每组的订单数量平均客单价

代码实操

# 模拟数据
store_data = {
    '城市': ['北京', '北京', '上海', '上海', '北京', '上海'],
    '门店类型': ['旗舰店', '标准店', '旗舰店', '标准店', '标准店', '旗舰店'],
    '订单数': [150, 200, 180, 220, 210, 195],
    '客单价': [350, 280, 400, 310, 270, 390]
}
df_store = pd.DataFrame(store_data)
# 多级分组:按城市和门店类型
# 使用 agg() 同时计算总和与均值
result_multi = df_store.groupby(['城市', '门店类型']).agg(
    总订单数=('订单数', 'sum'),
    平均客单价=('客单价', 'mean')
).reset_index()
print(result_multi)

运行结果

   城市  门店类型  总订单数  平均客单价
0  北京   旗舰店    150   350.0
1  北京   标准店    410   275.0  # 注意:北京标准店有两行,求和得到410
2  上海   旗舰店    375   395.0
3  上海   标准店    220   310.0

进阶技巧:如果你想对同一列应用多个聚合函数(如同时计算销售额的sumstd),可以这样写:

df_store.groupby('城市')['客单价'].agg(['mean', 'std', 'count'])

实战案例三:自定义聚合函数与分组后变换

场景描述

当内置聚合函数(如summean)无法满足需求时,我们需要自定义函数,计算每个分组中高于该组平均值的销售额占比,或者,你想给每个分组内的数据添加一列“本组排名”,而不压缩行数——这时要用transform()

案例:计算每个组内的百分比排名

# 另辟数据:学生成绩
score_data = {
    '班级': ['A', 'A', 'B', 'B', 'C'],
    '姓名': ['张三', '李四', '王五', '赵六', '陈七'],
    '成绩': [85, 92, 78, 88, 95]
}
df_score = pd.DataFrame(score_data)
# 自定义函数:返回每个成绩在所在班级内的百分位排名(0~1之间)
def percentile_rank(group):
    # group 是一个Series(该班级的所有成绩)
    return group.rank(pct=True)
# 使用 transform() 保持原有形状,添加新列
df_score['班级内排名'] = df_score.groupby('班级')['成绩'].transform(percentile_rank)
print(df_score)

输出

  班级  姓名  成绩  班级内排名
0   A  张三   85  0.500
1   A  李四   92  1.000
2   B  王五   78  0.500
3   B  赵六   88  1.000
4   C  陈七   95  1.000

为什么用transform()
因为transform()返回一个与原DataFrame行数相同的Series,可以方便地添加为一列,而apply()agg()会压缩行数,不适合这种“给原表添加统计特征”的需求。


常见问题与避坑指南(Q&A)

❓ 问题1:分组后为什么索引乱掉了?如何保持原顺序?

回答groupby()默认会按分组键排序(如果键是字符串,按字母顺序),如果你希望保留数据原顺序,请设置sort=False

df.groupby('类别', sort=False)['金额'].sum()

❓ 问题2:agg()apply() 有什么区别?

回答

  • agg():专门用于聚合操作(返回标量值),可以一次应用多个函数,返回的DataFrame行数等于组数。
  • apply():更通用,可以返回任意形状(标量、Series、DataFrame),如果返回标量,作用类似agg();如果返回Series,会展开成多行。性能上agg()通常更快,优先使用agg()实现聚合。

❓ 问题3:分组后如何过滤掉某些组(例如只保留总销售额大于1000的组)?

回答:使用filter()方法,它根据一个返回布尔值的函数保留整个组:

# 只保留组内总销售额 > 1000 的组
filtered = df_sales.groupby('类别').filter(lambda x: x['销售额'].sum() > 1000)

❓ 问题4:如何处理分组中的缺失值(NaN)?

回答:默认情况下,groupby()会排除所有包含NaN的分组键行,如果你希望将NaN也作为一个单独的分组,使用dropna=False

df.groupby('类别', dropna=False)['金额'].sum()

❓ 问题5:如何将分组统计结果可视化?

回答:分组统计结果通常是Series或DataFrame,可以直接用Matplotlib或Seaborn绘图。

import matplotlib.pyplot as plt
grouped = df_sales.groupby('类别')['销售额'].sum()
grouped.plot(kind='bar')
plt.show()

掌握分组统计的三大心法

通过以上三个由浅入深的案例,我们系统学习了Pandas数据分组统计的核心技能:

  1. 熟记“拆分-应用-组合”流程groupby()是拆分,聚合函数(agg()transform())是应用,返回结果是组合。
  2. 区分agg()transform()agg()用于压缩数据(行变少), transform()用于保留原行数添加统计特征。
  3. 善用多级分组与自定义函数,通过groupby([col1, col2])实现多维统计,通过lambdadef函数解决复杂逻辑。

数据分析没有银弹,但Pandas的groupby绝对是你武器库中最锋利的刀,建议在本地Jupyter Notebook中逐行运行以上案例,手动修改参数观察效果——实践是掌握数据分组统计的最佳途径。

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