如何基于共同键合并并累加两个 DataFrame 的行数据

2次阅读

如何基于共同键合并并累加两个 DataFrame 的行数据

本文介绍如何将第二个 dataframe 中与第一个 dataframe 共享主键(如 ‘name’ 列)的行数据,按列数值累加到第一个 dataframe 对应行中,忽略不匹配的行,并保持原始键的完整性。

本文介绍如何将第二个 dataframe 中与第一个 dataframe 共享主键(如 ‘name’ 列)的行数据,按列数值累加到第一个 dataframe 对应行中,忽略不匹配的行,并保持原始键的完整性。

数据分析实践中,常需对多个来源的同类记录进行“增量聚合”——即仅对已存在的实体(如用户、球员、产品)更新其指标,而不引入新实体、也不覆盖主键字段。本例中,df1 是基准数据表,df2 是增量更新表;目标是:仅当 df2 中某行的 ‘name’ 在 df1 中已存在时,才将其数值列(’goals’, ‘minutes’)加到 df1 对应行上,且 ‘name’ 本身不参与运算或重复写入

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

  1. 筛选并拼接:保留 df2 中 ‘name’ 出现在 df1 中的所有行,再与 df1 垂直拼接(pd.concat);
  2. 分组聚合:以 ‘name’ 为键分组,对所有数值列执行 sum()(自动跳过非数值列,且天然支持多列统一累加);
  3. 恢复结构:调用 .reset_index() 将分组键转回普通列,得到标准 DataFrame。

以下是完整可运行代码:

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

关键优势说明

  • 健壮性高:groupby(…).sum() 自动处理缺失列、空值(默认跳过),且无需预设列名;
  • 无副作用:不修改原 df1 或 df2,符合函数式编程原则;
  • 可扩展性强:若后续新增数值列(如 ‘assists’),代码无需更改;
  • 性能优秀:避免显式循环和逐行索引查找(如 iloc[position]),充分利用 pandas 向量化操作。

⚠️ 注意事项

  • 确保 ‘name’ 列类型一致(如均为 str),否则 isin() 可能返回意外结果;建议前置校验:df1[‘name’].dtype == df2[‘name’].dtype;
  • 若需保留 df1 中原始行顺序(如 ‘Bob’ 必须排第二),而 groupby 默认按字典序排序,可在最后按 df1[‘name’] 顺序重排:
    result = result.set_index('name').reindex(df1['name']).reset_index()
  • 该方法假设所有数值列均需累加;若需对不同列应用不同聚合逻辑(如 ‘minutes’ 取最大值、’goals’ 取和),则应改用 agg({‘goals’: ‘sum’, ‘minutes’: ‘max’})。

综上,此方案以声明式语法精准表达了业务意图:「对交集键做数值列累加」,兼顾可读性、性能与可维护性,是 pandas 数据融合任务中的推荐实践。

text=ZqhQzanResources