如何基于指定列替换DataFrame中部分行的指定列值
问题描述
现有两个Pandas DataFrame:
原始数据:
import pandas as pd import numpy as np df = pd.DataFrame({'c1': [10, 11, 12, 13], 'c2': [100, 110, 120, 130], 'c3': [100, 110, 120, 130], 'c4': ['A', np.nan, np.nan, 'B']})
用于替换的参考数据:
df_replacer = pd.DataFrame({'c2': [11, 22], 'c3': [99, 299], 'c4': ['A', 'B']})
需求是:通过c4列匹配,用df_replacer里的值替换df中c2、c3列的对应行(仅替换c4不为空的行)。
目前的实现代码如下,想找更简洁的写法:
df = df.merge(df_replacer, on=['c4'], how='left') df.loc[~df.c4.isna(), 'c2_x'] = df['c2_y'] df.loc[~df.c4.isna(), 'c3_x'] = df['c3_y'] df = df.rename({'c2_x': 'c2', 'c3_x':'c3'}, axis=1) df = df[['c1', 'c2', 'c3', 'c4']]
简洁实现方案
方案1:映射字典替换(最简洁)
先从替换表中构建c4到c2、c3的映射关系,再用map+fillna完成替换,全程不用合并表:
# 构建c4与c2、c3的映射字典 c2_map = df_replacer.set_index('c4')['c2'].to_dict() c3_map = df_replacer.set_index('c4')['c3'].to_dict() # 替换c2、c3列,c4为空的行保留原值 df['c2'] = df['c4'].map(c2_map).fillna(df['c2']) df['c3'] = df['c4'].map(c3_map).fillna(df['c3'])
方案2:简化合并后的操作
如果偏好使用merge,可以简化后续的赋值和重命名步骤,用where直接完成替换:
# 合并时指定后缀区分原列和替换列 merged_df = df.merge(df_replacer, on='c4', how='left', suffixes=('', '_repl')) # 仅对c4非空的行替换c2、c3值 merged_df['c2'] = merged_df['c2_repl'].where(~merged_df['c4'].isna(), merged_df['c2']) merged_df['c3'] = merged_df['c3_repl'].where(~merged_df['c4'].isna(), merged_df['c3']) # 保留需要的列 df = merged_df[['c1', 'c2', 'c3', 'c4']]
内容的提问来源于stack exchange,提问作者user13744439
相关产品推荐
相关产品推荐

