如何用另一Pandas DataFrame列更新指定列(类SQL UPDATE JOIN)
Pandas实现类似SQL UPDATE JOIN的原地更新操作
问题场景
我有两个Pandas DataFrame:
第一个DataFrame(First)
| Timestamp | Label | Value | Another col 1 | another col 2 |
|---|---|---|---|---|
| 2022-01-01 00:00 | A | 0 | ... | ... |
| 2022-01-01 00:00 | B | 0 | ... | ... |
| 2022-01-01 00:15 | B | 0 | ... | ... |
| 2022-01-01 00:30 | B | 0 | ... | ... |
| 2022-01-01 00:45 | B | 0 | ... | ... |
| 2022-01-01 01:00 | C | 0 | ... | ... |
| 2022-01-01 01:00 | D | 0 | ... | ... |
| 2022-01-01 01:15 | D | 0 | ... | ... |
| ... | ... | ... | ... | ... |
第二个DataFrame(Second)
| Timestamp | Label | Value | Unrelated column A | Unrelated column B |
|---|---|---|---|---|
| 2022-01-01 00:00 | A | 20 | ... | ... |
| 2022-01-01 01:00 | C | 20 | ... | ... |
| ... | ... | ... | ... | ... |
需求
- 提取Second DataFrame的所有行
- 通过
Timestamp和Label在First DataFrame中匹配行(忽略无法匹配的行) - 用
Second.Value的值更新First.Value列,最终得到如下结果:
更新后的First DataFrame
| Timestamp | Label | Value | Another col 1 | another col 2 |
|---|---|---|---|---|
| 2022-01-01 00:00 | A | 20 | ... | ... |
| 2022-01-01 00:00 | B | 0 | ... | ... |
| 2022-01-01 00:15 | B | 0 | ... | ... |
| 2022-01-01 00:30 | B | 0 | ... | ... |
| 2022-01-01 00:45 | B | 0 | ... | ... |
| 2022-01-01 01:00 | C | 20 | ... | ... |
| 2022-01-01 01:00 | D | 0 | ... | ... |
| 2022-01-01 01:15 | D | 0 | ... | ... |
| ... | ... | ... | ... | ... |
在SQL中可以用UPDATE JOIN实现,但不清楚Pandas的操作方式。试过DataFrame.update和DataFrame.merge,但它们更偏向完全合并,我只需要复制特定值,猜测可能用到多级索引但不熟悉,求帮助。
补充:有人询问是否与《Pandas Merging 101》重复,我认为不是,因为需要原地更新第一个数据集,merge似乎无法实现。
解决方案
方法一:多级索引 + update(原地更新,推荐)
通过设置Timestamp和Label为联合索引,利用update方法实现原地匹配更新,完全符合需求:
# 为两个DataFrame设置联合索引(匹配键) first_df.set_index(['Timestamp', 'Label'], inplace=True) second_df.set_index(['Timestamp', 'Label'], inplace=True) # 仅用Second的Value列更新First的对应列,自动忽略不匹配的行 first_df.update(second_df[['Value']]) # 可选:恢复原索引结构(如果不需要保留联合索引) first_df.reset_index(inplace=True)
方法二:merge + combine_first(生成新DataFrame)
如果不想修改索引,可以通过合并+值覆盖的方式生成更新后的DataFrame,再赋值给原变量:
# 提取Second中用于更新的必要列(匹配键+Value) second_update = second_df[['Timestamp', 'Label', 'Value']] # 左连接First和更新数据,添加后缀区分重复列 merged = first_df.merge(second_update, on=['Timestamp', 'Label'], how='left', suffixes=('', '_new')) # 用Second的Value覆盖匹配行,未匹配行保留原值 merged['Value'] = merged['Value_new'].combine_first(merged['Value']) # 删除临时列,得到最终结果 merged.drop(columns=['Value_new'], inplace=True) # 原地更新原DataFrame first_df = merged
内容的提问来源于stack exchange,提问作者Dalibor Čarapić
相关产品推荐
相关产品推荐

