
本文介绍如何提取 location 列的前缀(如 "1001 - bbb" → "1001"),对 available 和 sold 列按该前缀分组求和,并将结果广播回每一行,同时完整保留 name、local_id、more_data 等不可聚合的原始列。
本文介绍如何提取 location 列的前缀(如 "1001 - bbb" → "1001"),对 available 和 sold 列按该前缀分组求和,并将结果广播回每一行,同时完整保留 name、local_id、more_data 等不可聚合的原始列。
在实际数据分析中,常遇到“部分字段需聚合、部分字段需保留原始粒度”的混合需求。例如本例:location 字段含冗余后缀("1001 - BBB"),而 available/sold 值实际按前缀 "1001" 全局唯一;但 name、local_id、more_data 等列是每行独立标识,绝不能被 groupby().agg() 丢弃或错误汇总。
核心解法是组合使用 str.split() 提取前缀 + groupby().transform() 广播聚合结果:
# 步骤1:提取 location 前缀(如 "1001 - BBB" → "1001")
df['location'] = df['location'].str.split(' - ').str[0]
# 步骤2:对 available/sold 按新 location 分组,取每组唯一值之和,并广播到所有行
df[['available', 'sold']] = df.groupby('location')[['available', 'sold']].transform(
lambda x: x.unique().sum()
)✅ 关键点说明:
- transform() 保证输出长度与原 DataFrame 一致,自动对齐每行,避免索引错位;
- x.unique().sum() 显式去重再求和,精准匹配业务逻辑(同一 location 下重复值仅计一次);
- 其他列(name, local_id, more_data)完全不受影响,原样保留;
- assign() 或直接赋值均可,推荐链式写法提升可读性。
⚠️ 注意事项:
- 若 available/sold 存在 NaN,unique() 会保留 NaN,导致 sum() 返回 NaN。如有缺失值,建议预处理:
df[['available', 'sold']] = df[['available', 'sold']].fillna(0)
- str.split(' - ').str[0] 假设分隔符恒为 " - "。若格式不统一,可用正则 str.extract(r'^(\d+)') 更鲁棒;
- transform() 性能优于 merge 或 map,尤其在大数据集上优势明显。
最终效果:所有 "1001*" 行的 available 统一更新为 1903(1+1029+873),sold 更新为 612(0+237+375),其余列零改动——完美满足“聚合+保形”双重目标。


















