多条件下如何将子记录的DATA_FIELD更新为父记录对应值?
Pandas按父记录更新符合条件的子记录字段
数据场景
原始DataFrame定义如下:
import pandas as pd df = pd.DataFrame([[1,2,3,"P", 1, "A", "SOMETHING"], [1,2,3,"C", 0, "B", "NOTHING"], [1,2,3,"C", 0, "B", "SOMETHING"], [4,5,6,"P", 1, "A", "SOMETHING"], [4,5,6,"C", 1, "A", "NOTHING"]], columns=["ID1", "ID2", "ID3", "FLAG", "CONDITION_1", "CONDITION_2", "DATA_FIELD"])
输出结构:
ID1 ID2 ID3 FLAG CONDITION_1 CONDITION_2 DATA_FIELD 0 1 2 3 P 1 A SOMETHING 1 1 2 3 C 0 B NOTHING 2 1 2 3 C 0 B SOMETHING 3 4 5 6 P 1 A SOMETHING 4 4 5 6 C 1 A NOTHING
字段规则
- FLAG列取值:
- P: 父记录
- C: 子记录
- 当ID1、ID2、ID3完全相同时,记录属于同一关联组,每组必有1条父记录,可包含任意数量子记录。
需求
当子记录满足CONDITION_1 == 0 AND CONDITION_2 == "B"时,将其DATA_FIELD值替换为对应父记录的DATA_FIELD值。预期结果:
ID1 ID2 ID3 FLAG CONDITION_1 CONDITION_2 DATA_FIELD 0 1 2 3 P 1 A SOMETHING 1 1 2 3 C 0 B SOMETHING 2 1 2 3 C 0 B SOMETHING 3 4 5 6 P 1 A SOMETHING 4 4 5 6 C 1 A NOTHING
初始思路及代码
通过排序后逐行遍历,存储父记录信息,再匹配更新子记录:
df.sort_values(["ID1", "ID2", "ID3", "FLAG"], ascending=[True, True, True, False], inplace=True) df.reset_index(drop=True, inplace=True) parent_keys = None for index, row in df.iterrows(): if row["FLAG"] == "P": parent_keys = f"{row['ID1']}{row['ID2']}{row['ID3']}" parent_data_field_value = row["DATA_FIELD"] if row["FLAG"] == "C": if parent_keys: child_keys = f"{row['ID1']}{row['ID2']}{row['ID3']}" if child_keys == parent_keys: if row["CONDITION_1"] == 0 and row["CONDITION_2"] == "B": df.loc[index, "DATA_FIELD"] = parent_data_field_value
该方案逻辑直观,但逐行遍历iterrows()在数据量较大时效率极低,不符合Pandas矢量化运算的最优实践。
优化方案:矢量化实现
利用Pandas的分组、合并功能,无需遍历即可完成高效更新:
步骤1:提取父记录的DATA_FIELD值
筛选出父记录,保留关联ID和对应的DATA_FIELD字段:
parent_data = df[df["FLAG"] == "P"][["ID1", "ID2", "ID3", "DATA_FIELD"]].rename(columns={"DATA_FIELD": "PARENT_DATA"})
步骤2:合并父记录数据到原DataFrame
通过关联ID将父记录的PARENT_DATA合并到原表:
df_merged = df.merge(parent_data, on=["ID1", "ID2", "ID3"], how="left")
步骤3:条件更新子记录字段
使用Pandas的loc进行矢量化条件替换:
# 定义更新条件:子记录 + 满足指定CONDITION规则 update_condition = (df_merged["FLAG"] == "C") & (df_merged["CONDITION_1"] == 0) & (df_merged["CONDITION_2"] == "B") # 执行字段更新 df_merged.loc[update_condition, "DATA_FIELD"] = df_merged.loc[update_condition, "PARENT_DATA"] # 清理临时字段 df_final = df_merged.drop(columns=["PARENT_DATA"])
最终结果
df_final即为预期的更新后DataFrame,该方案完全基于矢量化运算,处理大数据量时性能远高于遍历方案。
内容的提问来源于stack exchange,提问作者Looz
相关产品推荐
相关产品推荐

