如何基于共同键(name)合并两个DataFrame并按行累加数值列

4次阅读

如何基于共同键(name)合并两个DataFrame并按行累加数值列

本文介绍使用pandas高效实现“按指定列(如name)对齐,仅对df1中已存在的记录,将df2对应行的数值列累加到df1”的操作,核心方法是过滤+拼接+分组求和。

本文介绍使用pandas高效实现“按指定列(如name)对齐,仅对df1中已存在的记录,将df2对应行的数值列累加到df1”的操作,核心方法是过滤+拼接+分组求和。

数据分析etl流程中,常需将新批次数据(如每日更新的球员统计)增量合并到主数据表中:仅对主表(df1)中已存在的实体(如球员姓名),将其在新表(df2)中的数值字段(如goals、minutes)进行累加;而新表中独有的记录(如Steve)应被忽略,主表中无匹配的新记录(如Bob在df2中未出现)则保持原值不变。

最简洁、高效且符合Pandas惯用法的解决方案是三步链式操作:

  1. 过滤 df2:仅保留 name 在 df1 中存在的行;
  2. 纵向拼接:将 df1 与过滤后的 df2 合并;
  3. 分组聚合:按 name 分组,对所有数值列执行 sum(),自动完成同名行的数值累加,并通过 reset_index() 恢复 name 为普通列。

以下是完整可运行代码示例:

import pandas as pd  # 构建示例数据 df1 = pd.DataFrame([     {'name': 'Ben', 'goals': 1, 'minutes': 90},     {'name': 'Bob', 'goals': 1, 'minutes': 64},     {'name': 'Kevin', 'goals': 1, 'minutes': 90} ])  df2 = pd.DataFrame([     {'name': 'Ben', 'goals': 1, 'minutes': 88},     {'name': 'Kevin', 'goals': 1, 'minutes': 3},     {'name': 'Steve', 'goals': 1, 'minutes': 13} ])  # 核心操作:过滤 → 拼接 → 分组求和 → 重置索引 result = (     pd.concat([df1, df2.loc[df2["name"].isin(df1["name"])]])     .groupby("name", as_index=False)     .sum() )  print(result)

输出结果:

name  goals  minutes 0    Ben      2      178 1    Bob      1       64 2  Kevin      2       93

关键优势说明

  • 向量化高效:完全避免显式循环或逐行判断,充分利用Pandas底层优化;
  • 健壮性高:groupby(…).sum() 自动跳过非数值列(若存在),且对缺失值(NaN)默认忽略(可通过 min_count=1 控制);
  • 语义清晰:逻辑直白——“只合并共有的名字,然后加总”,易于团队协作与后期维护。

⚠️ 注意事项

  • 若数据中存在重复 name(如 df1 内部已有多个 Ben),groupby.sum() 会将其全部合并,需提前去重(如 df1.drop_duplicates(subset=’name’, keep=’first’));
  • 确保参与累加的列均为数值类型(int/Float),否则 sum() 可能报错或触发隐式类型转换;可预先校验:df1.select_dtypes(include=’number’).columns;
  • 如需保留原始索引顺序(如按 df1 中 name 的出现顺序排列结果),可在最后添加 .reindex(df1[‘name’].unique(), fill_value=0) 配合 set_index(‘name’),但本例因 groupby 默认按字典序排序,故推荐在 groupby 前对拼接数据预排序,或使用 sort=False 参数(Pandas ≥ 1.1)。

该方法是处理“主表增量数值更新”场景的标准范式,兼顾性能、可读性与可扩展性,推荐作为首选方案。

text=ZqhQzanResources