如何用多DataFrame按指定列映射并保留已有映射数据
保留多数据源映射的非空数据解决方案
场景与问题
我们有三个DataFrame:df_1、df_2、df_3,其中df_2是基础数据表,需要从df_1和df_3中补充status字段。但直接两次用map赋值会覆盖之前的非空数据,导致部分已填充的状态丢失。
初始代码与问题复现
首先创建示例数据:
import pandas as pd # 创建示例DataFrame df_1 = pd.DataFrame({ "name": ["Alice"], "age": [25], "status": ["Single"] }) df_2 = pd.DataFrame({ "name": ["Alice", "Charlie", "Dave"], "time": ["9:00 AM", "10:00 AM", "11:00 AM"] })
第一次映射后,df_2的status字段已有部分值:
status_map = dict(zip(df_1["name"], df_1["status"])) df_2["status"] = df_2["name"].map(status_map)
此时df_2输出:
name time status 0 Alice 9:00 AM Single 1 Charlie 10:00 AM NaN 2 Dave 11:00 AM NaN
但用df_3直接映射赋值时,原有非空数据会被覆盖:
df_3 = pd.DataFrame({ "name": ["Dave"], "age": [25], "status": ["Married"] }) status_map_df3 = dict(zip(df_3["name"], df_3["status"])) df_2["status"] = df_2["name"].map(status_map_df3)
输出变成:
name time status 0 Alice 9:00 AM NaN 1 Charlie 10:00 AM NaN 2 Dave 11:00 AM Married
我们需要保留两次映射的有效数据,得到目标结果:
name time status 0 Alice 9:00 AM Single 1 Charlie 10:00 AM NaN 2 Dave 11:00 AM Married
解决方案
方法1:合并映射字典后一次性映射
先把两个状态字典合并,再一次性映射到df_2,避免重复赋值覆盖:
# 合并两个映射字典(后加入的字典不会覆盖已有键,除非键重复) combined_status_map = {**status_map, **status_map_df3} # 或者用copy+update的方式,更直观: # combined_status_map = status_map.copy() # combined_status_map.update(status_map_df3) # 一次性完成映射 df_2["status"] = df_2["name"].map(combined_status_map)
方法2:用fillna填充缺失值
如果已经完成第一次映射,用第二次映射的结果填充原有status的NaN,不覆盖已有的非空值:
# 第一次映射完成 df_2["status"] = df_2["name"].map(status_map) # 用第二次映射结果填充NaN df_2["status"] = df_2["status"].fillna(df_2["name"].map(status_map_df3))
方法3:多表合并(适合扩展场景)
如果后续还有更多状态数据源,推荐把所有状态表合并后,和df_2做左连接,扩展性更强:
# 合并所有状态数据源,只保留name和status字段 all_status = pd.concat([df_1[["name", "status"]], df_3[["name", "status"]]]) # 去重(如果有重复name,保留最后一条的状态) all_status = all_status.drop_duplicates(subset="name", keep="last") # 和df_2左连接,补充status字段 df_2 = df_2.merge(all_status, on="name", how="left")
内容的提问来源于stack exchange,提问作者hacaho
相关产品推荐
相关产品推荐

