如何基于多候选键列合并两个Pandas DataFrame
如何基于多候选键列合并两个DataFrame?
首先先复现你提供的示例数据:
import pandas as pd import numpy as np # 初始化df1 df1 = pd.DataFrame([[1,10,100],[2,20,np.nan],[3,30,300]], columns=["A","B","C"]) # 初始化df2 df2 = pd.DataFrame([[1,422],[10,72],[2,278],[300,198]], columns=["ID","Value"])
你的需求是:让df2的ID列匹配df1中A/B/C任意一列的值,只要匹配上就进行关联合并,最终保留所有匹配的结果(比如df1第一行同时匹配df2的ID=1和ID=10,所以输出两行)。
实现思路
核心思路是将df1的多候选键列转换为长格式,这样就能用单列和df2的ID做关联,之后再整理回目标格式:
- 给df1添加临时行标识,方便后续关联回原始行数据
- 使用
pd.melt把df1的A/B/C列转成键值对形式,统一成ID列 - 过滤掉
ID为NaN的行(避免无效匹配),然后和df2做内连接 - 清理临时列,整理成目标输出格式
完整代码实现
import pandas as pd import numpy as np # 初始化原始数据 df1 = pd.DataFrame([[1,10,100],[2,20,np.nan],[3,30,300]], columns=["A","B","C"]) df2 = pd.DataFrame([[1,422],[10,72],[2,278],[300,198]], columns=["ID","Value"]) # 步骤1:添加临时行ID,用于关联原始行数据 df1['row_id'] = df1.index # 步骤2:将df1的A/B/C列转成长格式,生成统一的ID列 df1_melted = df1.melt( id_vars=['row_id', 'A', 'B', 'C'], # 保留需要的原始列 value_vars=['A', 'B', 'C'], # 指定要转换的候选键列 value_name='ID' # 转换后的键列名,和df2的ID对应 ) # 步骤3:过滤NaN的ID,和df2做内连接 merged = df1_melted.dropna(subset=['ID']).merge(df2, on='ID', how='inner') # 步骤4:清理临时列,整理成目标格式 df_output = merged.drop(columns=['variable', 'row_id']).reset_index(drop=True) print(df_output)
运行后输出结果和你预期的完全一致:
A B C Value 0 1 10 100.0 422 1 1 10 100.0 72 2 2 20 NaN 278 3 3 30 300.0 198
关键细节说明
pd.melt的作用是把宽格式的多候选键列“压扁”成单列,这样就能和df2的ID做一对一的匹配,完美解决多列匹配的问题dropna(subset=['ID'])会过滤掉df1中候选键为NaN的行,避免这些NaN尝试和df2的ID匹配(毕竟df2的ID都是有效数值)- 使用
inner连接可以只保留两边都匹配上的结果,符合你示例中的输出逻辑
内容的提问来源于stack exchange,提问作者Amit V
相关产品推荐
相关产品推荐

