如何在Python中基于变更请求增量更新DataFrame?
说明
- 我有一个包含原始数据和更新记录的文件。
- original_id字段可视为主键。
- change_request_id字段为空的行是初始数据条目。
- change_request_id字段有值的行是对初始数据条目的更新。
- change_request_id字段关联目标初始数据的original_id,表示数据变更(更新)。仅需变更的字段会填充值,空字段表示该值保持不变。
原始文件
| change_request_id | original_id | a | b | c | d |
|---|---|---|---|---|---|
| 1 | 10 | 20 | 30 | 40 | |
| 2 | 2500 | 600 | 700 | 800 | |
| 1 | 3 | 12 | |||
| 2 | 4 | 700 | 800 | ||
| 1 | 5 | 30 | |||
| 6 | 16 | 17 | 19 | 20 |
期望输出
| change_request_id | original_id | a | b | c | d |
|---|---|---|---|---|---|
| 1 | 12 | 30 | 30 | 40 | |
| 2 | 500 | 700 | 800 | 800 | |
| 6 | 16 | 17 | 19 | 20 |
Python实现方法
以下是使用Pandas实现增量更新的代码,核心逻辑是分离初始数据与更新记录,聚合同一初始数据的所有更新操作,最后用非空的更新值覆盖初始数据:
import pandas as pd import numpy as np # 1. 构造或读取原始数据(实际场景可替换为pd.read_csv等文件读取方法) data = { 'change_request_id': ['', '', '1', '2', '1', ''], 'original_id': [1, 2, 3, 4, 5, 6], 'a': [10, 2500, 12, np.nan, np.nan, 16], 'b': [20, 600, np.nan, 700, 30, 17], 'c': [30, 700, np.nan, 800, np.nan, 19], 'd': [40, 800, np.nan, np.nan, np.nan, 20] } df = pd.DataFrame(data) # 2. 分离初始数据和更新记录 initial_df = df[df['change_request_id'] == ''].copy() updates_df = df[df['change_request_id'] != ''].copy() # 3. 转换字段类型,确保关联匹配 updates_df['change_request_id'] = updates_df['change_request_id'].astype(int) initial_df['original_id'] = initial_df['original_id'].astype(int) # 4. 聚合同一初始数据的所有更新:取每个字段最后一次非空的更新值(后续更新覆盖前序) agg_rules = {col: lambda x: x.dropna().iloc[-1] if not x.dropna().empty else np.nan for col in ['a', 'b', 'c', 'd']} update_summary = updates_df.groupby('change_request_id').agg(agg_rules).reset_index() update_summary.rename(columns={'change_request_id': 'original_id'}, inplace=True) # 5. 用更新值覆盖初始数据,仅替换非空字段 final_df = initial_df.set_index('original_id').combine_first(update_summary.set_index('original_id')).reset_index() # 6. 恢复change_request_id为空字符串,调整列顺序与原始一致 final_df['change_request_id'] = '' final_df = final_df[['change_request_id', 'original_id', 'a', 'b', 'c', 'd']] # 查看最终结果 print(final_df)
代码说明
- 分离数据:通过
change_request_id是否为空,拆分出初始数据和待处理的更新记录。 - 聚合更新:按关联的初始数据ID分组,对每个字段保留最后一次非空的更新值,保证后续更新操作覆盖之前的变更。
- 合并覆盖:使用
combine_first方法,仅用更新记录中的非空值替换初始数据对应字段,未变更的字段保留原始值。
内容的提问来源于stack exchange,提问作者Jogibaer
相关产品推荐
相关产品推荐

