
本文介绍如何将第二个 dataframe 中与第一个 dataframe 共享主键(如 'name' 列)的行数据,按列数值累加到第一个 dataframe 对应行中,忽略不匹配的行,并保持原始键的完整性。
本文介绍如何将第二个 dataframe 中与第一个 dataframe 共享主键(如 'name' 列)的行数据,按列数值累加到第一个 dataframe 对应行中,忽略不匹配的行,并保持原始键的完整性。
在数据分析实践中,常需对多个来源的同类记录进行“增量聚合”——即仅对已存在的实体(如用户、球员、产品)更新其指标,而不引入新实体、也不覆盖主键字段。本例中,df1 是基准数据表,df2 是增量更新表;目标是:仅当 df2 中某行的 'name' 在 df1 中已存在时,才将其数值列('goals', 'minutes')加到 df1 对应行上,且 'name' 本身不参与运算或重复写入。
最简洁、高效且符合 pandas 惯用法的解决方案是采用三步链式操作:
- 筛选并拼接:保留 df2 中 'name' 出现在 df1 中的所有行,再与 df1 垂直拼接(pd.concat);
- 分组聚合:以 'name' 为键分组,对所有数值列执行 sum()(自动跳过非数值列,且天然支持多列统一累加);
- 恢复结构:调用 .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 数据融合任务中的推荐实践。










