连接具有多个公共列的多个数据框

时间:2020-05-28 03:42:31

标签: python python-3.x pandas

我有多个这样的数据框-

df=pd.DataFrame({'a':[1,2,3],'b':[3,4,5],'c':[4,6,7]})
df2=pd.DataFrame({'a':[1,2,3],'d':[66,24,55],'c':[4,6,7]})
df3=pd.DataFrame({'a':[1,2,3],'f':[31,74,95],'c':[4,6,7]})

我想要这个输出-

    a   c
0   1   4
1   2   6
2   3   7

这是3个数据集中的公共列。我正在寻找一种适用于多列的解决方案,而不必像我在SO上看到的那样指定公共列(因为实际数据帧很大)。

3 个答案:

答案 0 :(得分:0)

reduceintersectionfilterconcat的组合可以帮助您解决用例:

DB::rollback()

如果列和列的内容相同,那么您可以跳过列表理解,而仅从一个数据帧中进行过滤:

DB::rollback()

如果列的内容不同,则串联并删除重复项:

dfs = (df,df2,df3)
cols = [ent.columns for ent in dfs]
cols

[Index(['a', 'b', 'c'], dtype='object'),
 Index(['a', 'd', 'c'], dtype='object'),
 Index(['a', 'f', 'c'], dtype='object')]

#find the common columns to all : 
from functools import reduce
universal_cols = reduce(lambda x,y : x.intersection(y), cols).tolist()
universal_cols

['a', 'c']

#filter for only universal_cols for each df
updates = [ent.filter(universal_cols) for ent in dfs]

答案 1 :(得分:0)

您可以使用reduce,将函数r_common从左到右累积应用于dfs的数据帧,以便将dfs的列表简化为单个数据帧df_commonintersection方法用于在d1函数内部的两个数据帧d2r_common中找出公共列。

def r_common(d1, d2):
    cols = d1.columns.intersection(d2.columns).tolist()
    m =  d1[cols].eq(d2[cols]).all()
    return d1[m[m].index]

df_common = reduce(r_common, dfs) # dfs = [df, df2, df3]

结果:

# print(df_common)
   a  c
0  1  4
1  2  6
2  3  7

答案 2 :(得分:0)

如果需要在每个DataFrame中具有相同内容的过滤器列名称,可以将其转换为元组并进行比较:

dfs = [df, df2, df3]  
df1 = pd.concat([x.apply(tuple) for x in dfs], axis=1)
cols = df1.index[df1.eq(df1.iloc[:, 0], axis=0).all(axis=1)]

df2 = df[cols]
print (df2) 
   a  c
0  1  4
1  2  6
2  3  7

如果列名应该不同并且有必要,则仅比较内容:

df=pd.DataFrame({'a':[1,2,3],'b':[3,4,5],'c':[4,6,7]})
df2=pd.DataFrame({'r':[1,2,3],'t':[66,24,55],'l':[4,6,7]})
df3=pd.DataFrame({'f':[1,2,3],'g':[31,74,95],'m':[4,6,7]})

dfs = [df, df2, df3]  
p = [x.apply(tuple).tolist() for x in dfs]
a = set(p[0]).intersection(*p)
print (a) 
{(4, 6, 7), (1, 2, 3)}