pandas如何对DataFrame取交集且不生成额外重复列
问题描述
对两个结构相同的pandas DataFrame做交集操作时,无论是用pd.merge还是pd.concat,都会生成带后缀的重复列,无法得到预期的纵向拼接、带来源标记的交集结果。
示例数据
两个测试用DataFrame列名完全一致,仅列A的取值范围有重叠:
import pandas as pd import numpy as np df1 = pd.DataFrame( data = np.stack([ np.arange(4), np.random.rand(4), np.random.rand(4), ],axis=-1), columns = ["A","B","C"] ) df2 = pd.DataFrame( data = np.stack([ np.arange(4)+2, np.random.rand(4), np.random.rand(4), ],axis=-1), columns = ["A","B","C"] )
两个DataFrame的输出示例:
( A B C 0 0.0 0.165849 0.516438 1 1.0 0.116661 0.395433 2 2.0 0.758229 0.386642 3 3.0 0.057719 0.802317, A B C 0 2.0 0.899924 0.545800 1 3.0 0.792242 0.187410 2 4.0 0.332168 0.778160 3 5.0 0.164429 0.509884)
预期输出
需要保留两个DataFrame中A列取值重叠的行,同时增加Source列标记数据来源,结果为纵向拼接格式,无重复列:
Source A B C 2 df1 2.0 0.758229 0.386642 3 df1 3.0 0.057719 0.802317 0 df2 2.0 0.899924 0.545800 1 df2 3.0 0.792242 0.187410
已尝试的错误方案
方案1:用pd.concat横向拼接
将A设为索引后做横向内连接,会直接把两个表的非连接列横向并排,生成重复列名:
for df in [df1,df2]: df.set_index("A",inplace=True) df = pd.concat([df1,df2],join="inner",axis=1).reset_index()
输出结果:
A B C B C 0 2.0 0.758229 0.386642 0.899924 0.54580 1 3.0 0.057719 0.802317 0.792242 0.18741
方案2:用pd.merge内连接
直接按A列做内连接,非连接列会自动加_x/_y后缀,同样是横向拼接的重复列:
df = pd.merge( left = df1, right = df2, how="inner", on = "A" )
输出结果:
A B_x C_x B_y C_y 0 2.0 0.758229 0.386642 0.899924 0.54580 1 3.0 0.057719 0.802317 0.792242 0.18741
解决方案
之前的方法核心问题是拼接方向搞错了:axis=1的concat、默认的merge都是横向拼接,会把两个表的列并排展开,同名列必然重复。需求本身是纵向堆叠行,用默认axis=0的concat,提前筛掉A列不在交集内的行即可,代码非常简洁:
# 提取两个表A列的共有取值 common_a = np.intersect1d(df1['A'], df2['A']) # 分别筛选交集行、加来源标记,最后纵向拼接 res = pd.concat([ df1[df1['A'].isin(common_a)].assign(Source='df1'), df2[df2['A'].isin(common_a)].assign(Source='df2') ], ignore_index=False)[['Source','A','B','C']]
运行结果和预期完全一致:
Source A B C 2 df1 2.0 0.758229 0.386642 3 df1 3.0 0.057719 0.802317 0 df2 2.0 0.899924 0.545800 1 df2 3.0 0.792242 0.187410
如果需要重置行索引,在代码末尾加.reset_index(drop=True)即可。
内容的提问来源于stack exchange,提问作者carlitador
相关产品推荐
相关产品推荐

