
本文介绍如何提取 location 字段的前缀(如 "1001"),按该前缀分组对 available/sold 列求唯一值之和,并将结果广播回每一行,同时完整保留 name、local_id、more_data 等非聚合列。
本文介绍如何提取 location 字段的前缀(如 "1001"),按该前缀分组对 available/sold 列求唯一值之和,并将结果广播回每一行,同时完整保留 name、local_id、more_data 等非聚合列。
在实际数据分析中,常遇到类似场景:原始数据中 location 字段包含复合标识(如 "1001 - BBB"),而 available 和 sold 数值是按整个 location 重复记录的(即同一 location 下所有行的 available 值相同);但我们需要按 location 的前缀部分(如 "1001")聚合统计,同时不丢失原始行粒度信息——即保留每行的 name、local_id、more_data 等个体属性。
核心难点在于:既要实现跨子组(如 "1001 - BBB"、"1001 - GG"、"1001 - P")的数值聚合,又要避免使用 groupby().agg() 导致行数坍缩,从而破坏原有结构。
✅ 正确解法是组合使用:
- str.split(' - ').str[0] 提取 location 前缀;
- groupby().transform() 将聚合结果广播回原 DataFrame 所有对应行;
- 对 available/sold 使用 x.unique().sum() 确保重复值仅计算一次(因原始数据中同 location 下这两列完全重复)。
以下是完整可执行代码:
import pandas as pd
# 示例数据(简化版,实际中请替换为你的 DataFrame)
df = pd.DataFrame({
'location': ['1001 - BBB', '1001 - BBB', '1001 - GG', '1001 - GG', '1002 - GG'],
'available': [1, 1, 1029, 1029, 37],
'sold': [0, 0, 237, 237, 11],
'name': ['Alpha', 'Alpha', 'Charlie', 'Charlie', 'Charlie'],
'local_id': [24, 24, 6, 6, 6],
'more_data': ['DJQ3DD3y', 'aB3joXQy', 'VJYxnGXB', 'Vy9Mo52y', 'EyGMWPbJ']
})
# 步骤 1:提取 location 前缀(如 "1001")
df['location'] = df['location'].str.split(' - ').str[0]
# 步骤 2:按新 location 分组,对 available/sold 计算唯一值之和,并广播到每行
agg_cols = ['available', 'sold']
df[agg_cols] = df.groupby('location')[agg_cols].transform(
lambda x: x.unique().sum()
)
print(df)? 关键说明与注意事项:
- transform 是本方案的灵魂:它保持输出长度与输入一致,完美匹配原始行索引,避免 merge 或 map 带来的复杂性;
- x.unique().sum() 显式去重求和,比直接 sum() 更鲁棒(即使某组内 available 偶有微小差异,也能确保逻辑正确);
- 其他列(name, local_id, more_data)无需处理,天然保留原值;
- 若需保留原始 location 字段用于后续参考,可先创建新列(如 loc_prefix),再 groupby 该列,最后 drop 或重命名;
- 性能友好:全程向量化操作,适用于万级至百万级数据。
最终效果:每行 location 变为 "1001" 或 "1002",available/sold 更新为对应前缀下所有子 location 的唯一值总和,其余列毫发无损——真正实现“聚合不丢行,求和不误码”。


















