拆分、施法、合并:Pandas groupby 的全景实战与工程最佳实践

拆分、施法、合并:Pandas groupby 的全景实战与工程最佳实践

你以为自己在用 groupby 汇总数据,实际上你在设计一条“管道”:把复杂数据按语义拆开、在局部施以规则、再把结果合上。这就是 split-apply-combine。


开篇引入

Python 从“优雅的脚本语言”成长为数据时代的生产力引擎,离不开 Pandas 在数据整形与分析上的强大表达力。无论是电商日常报表、风控特征聚合,还是实验日志分析,groupby 都是高频工具。它背后的思想非常简单却无处不在:把数据按键划分为子集(Split),对每个子集应用函数(Apply),最终再拼回一个结构化结果(Combine)。理解这个过程,你会写出更直观、更高效、更可靠的数据管道。

  • 为什么写这篇文章:多年工程实践里,我见过太多“能跑但慢”“结果对但不可维护”的 groupby。本文从原理到实战,从 API 到性能,带你把 groupby 用得漂亮、稳健。
  • 你将获得:groupby 的心智模型、语法全景、聚合/变换/过滤的区别、复杂场景的模板、性能与内存优化策略、常见坑与排错清单。

基础概念:什么是 split-apply-combine

  • Split(拆分):按一个或多个键,把 DataFrame 分割成若干“组”。键可以是列名、索引层、函数(按规则分箱)、字典/Series(自定义映射),甚至是多个来源的组合。
  • Apply(施法):对每个组应用函数。函数可以是聚合(reduce 到标量)、变换(保留原行数)、过滤(丢弃不满足条件的组),或任意自定义。
  • Combine(合并):把各组的结果拼接为新的 Series 或 DataFrame,并在索引上保留组键的语义(单层或 MultiIndex)。

心智模型:把 groupby(keys) 看成“把 keys 作为索引”,在“每个键的切片”上执行函数,再把切片结果叠回去。


入门例子:一眼看懂聚合、变换、过滤

import pandas as pd
import numpy as np

df = pd.DataFrame({
   
   
    "city": ["Tokyo", "Tokyo", "Osaka", "Osaka", "Nagoya"],
    "cat":  ["A",     "B",     "A",     "B",     "A"],
    "qty":  [2, 3, 5, 1, 4],
    "price":[10, 20, 30, 40, 50],
    "user": [101,102,201,202,301]
})

g = df.groupby(["city", "cat"], as_index=True)

# 1) 聚合(Aggregation):每组变一个标量
agg_df = g.agg(
    orders=("user", "nunique"),
    qty_sum=("qty", "sum"),
    price_mean=("price", "mean"),
)
# 结果:行数=组数,索引为 (city, cat)

# 2) 变换(Transform):每行都保留,按组广播结果
df["qty_zscore"] = g["qty"].transform(lambda s: (s - s.mean()) / (s.std(ddof=0) + 1e-8))
# 结果:与原 df 同行数,常用于特征标准化

# 3) 过滤(Filter):保留满足条件的组(整组保留或整组丢弃)
df_big_groups = g.filter(lambda sub: sub["user"].nunique() >= 2)
# 结果:丢掉小组的所有行

选择哪一种,取决于你想要“行数变不变”和“输出聚合到什么层级”。


语法全景:从 keys 到 agg 的丰富表达

groupby 的 keys(分组键)

  • 列名或列名列表:
    df.groupby("city")
    df.groupby(["city", "cat"])
    
  • 索引层或层名:
    df2 = df.set_index(["city", "cat"])
    df2.groupby(level="city")
    
  • 映射/函数:
    # 映射:把城市归到大区
    region_map = {
         
         "Tokyo": "East", "Osaka": "West", "Nagoya"</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清水白石008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值