如何从其他DataFrame为NaN行补充数据且保留原有NaN值
问题描述与解决方法
问题场景
我有三个DataFrame:
import pandas as pd import numpy as np df_main = pd.DataFrame({'ID': ['10', '11', '12', '13', '14', '15', '16'], 'Name': [ np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]}) # df_main 输出: # ID Name # 0 10 NaN # 1 11 NaN # 2 12 NaN # 3 13 NaN # 4 14 NaN # 5 15 NaN # 6 16 NaN df2 = pd.DataFrame({'ID': ['10', '11', '12'], 'Name': [ 'Peter', 'Bruce', 'Tony']}) # df2 输出: # ID Name # 0 10 Peter # 1 11 Bruce # 2 12 Tony df3 = pd.DataFrame({'ID': ['15', '16'], 'Name': ['Wanda', 'Natasha']}) # df3 输出: # ID Name # 0 15 Wanda # 1 16 Natasha
期望结果是从df2和df3中提取对应ID的Name值补充到df_main的对应行,同时保留无匹配ID的NaN:
ID Name 0 10 Peter 1 11 Bruce 2 12 Tony 3 13 NaN 4 14 NaN 5 15 Wanda 6 16 Natasha
我尝试了以下循环代码但未生效:
for id in df2['ID'].unique(): if id in df_main['ID'].unique(): df_main.loc[df_main['ID'] == id, 'Name'] = df2.loc[df2['ID'] == id, 'Name'] for id in df3['ID'].unique(): if id in df_main['ID'].unique(): df_main.loc[df_main['ID'] == id, 'Name'] = df3.loc[df3['ID'] == id, 'Name']
可行解决方法
方法1:合并映射表后用combine_first填充
先将df2和df3合并成完整的ID-Name映射表,再用combine_first把缺失值填充到df_main中:
# 合并df2和df3得到完整映射 df_combined = pd.concat([df2, df3]).set_index('ID') # 填充df_main的Name列 df_main['Name'] = df_main.set_index('ID')['Name'].combine_first(df_combined['Name']).reset_index(drop=True)
方法2:使用update方法
update会自动用非NaN值更新原DataFrame,适合这类匹配更新场景:
# 合并df2和df3 df_combined = pd.concat([df2, df3]) # 通过合并提取匹配的Name值,更新原表 df_main.update(df_main.merge(df_combined, on='ID', how='left', suffixes=('', '_new'))['Name_new'])
方法3:修复原循环代码
原循环失效的原因是赋值时传入的是Series而非标量值,修改后即可生效:
# 处理df2的匹配ID for id in df2['ID'].unique(): if id in df_main['ID'].values: df_main.loc[df_main['ID'] == id, 'Name'] = df2.loc[df2['ID'] == id, 'Name'].iloc[0] # 处理df3的匹配ID for id in df3['ID'].unique(): if id in df_main['ID'].values: df_main.loc[df_main['ID'] == id, 'Name'] = df3.loc[df3['ID'] == id, 'Name'].iloc[0]
内容的提问来源于stack exchange,提问作者Mert Erişen
相关产品推荐
相关产品推荐

