Pandas如何合并重复行 对指定数值列求和且不修改字符串列
Pandas按uid分组合并重复行高效方案
核心需求回顾
- 以
uid为分组键,合并所有同uid的重复行 - 数值列聚合要求:
content post volume、views、exploration volume三个字段按分组求和 - 非数值列处理要求:
user_level按F1 < F2 < F3 < F4…的优先级取等级最高(序号最小)的取值Account type保留原始值,不做字符串拼接- 其余字符串列保留有效值即可,无需特殊聚合
原有方案的典型问题
- 直接调用
df.groupby("uid").sum()会触发pandas默认聚合逻辑,对字符串类型列做字符拼接,生成F1F3、F4F1这类无效值,导致后续无法按Account type字段做筛选。后续尝试用.str.split("F")拆分拼接字符串的方案无法逐单元格生效,不能满足筛选需求。 - 手动遍历重复uid、逐行计算求和再拼接结果的方案完全依赖Python循环,没有利用pandas的向量化优化,性能极差,1500条数据处理就需要3秒,数据量提升后完全不可用。
实现代码
核心思路是为groupby传入列与聚合函数的映射字典,为不同列指定独立的聚合规则,全程使用pandas内置的向量化运算,性能比手动循环提升100倍以上。
import pandas as pd # 1. 预处理user_level为有序分类,保证聚合时按指定优先级取值 all_levels = sorted(df["user_level"].dropna().unique(), key=lambda x: int(x[1:])) df["user_level"] = pd.Categorical( df["user_level"], categories=all_levels, ordered=True ) # 2. 构建各列的聚合规则 agg_config = { # 三个数值列执行求和 "content post volume": "sum", "views": "sum", "exploration volume": "sum", # user_level取优先级最高值(有序分类的min()会返回优先级最靠前的等级) "user_level": "min", # Account type取分组内第一个非空原始值,不会触发拼接 "Account type": "first" } # 其余未单独配置的列,统一取分组内第一个非空值 for col in df.columns: if col not in ["uid"] + list(agg_config.keys()): agg_config[col] = "first" # 3. 执行分组聚合,输出最终结果 result_df = df.groupby("uid", as_index=False).agg(agg_config)
方案说明
- 性能表现:所有聚合逻辑由pandas底层C实现,10万条规模的数据处理耗时通常在0.1秒以内,无性能瓶颈
- 结果准确性:从根源避免了字符串列被自动拼接的问题,
Account type等字段保留原始格式,完全支持后续的筛选、统计操作 - 扩展性:后续如果需要调整某列的聚合规则,只需要修改
agg_config字典中对应列的聚合函数即可,不需要改动核心逻辑
内容的提问来源于stack exchange,提问作者joe Qi
相关产品推荐
相关产品推荐

