【问题标题】:Find equal columns between two dataframes在两个数据框之间查找相等的列
【发布时间】:2020-04-30 10:22:00
【问题描述】:

我有两个 pandas 数据框,ab

a1   a2   a3   a4   a5   a6   a7
1    3    4    5    3    4    5
0    2    0    3    0    2    1
2    5    6    5    2    1    2

b1   b2   b3   b4   b5   b6   b7
3    5    4    5    1    4    3
0    1    2    3    0    0    2
2    2    1    5    2    6    5

这两个数据框包含完全相同的数据,但顺序不同,列名也不同。根据两个数据框中的数字,我希望能够将a 中的每个列名与b 中的每个列名匹配。

这并不像简单地将a 的第一行与b 的第一行进行比较那样简单,因为存在重复值,例如a4a7 都有值5 所以它无法立即将它们与b2b4 匹配。

最好的方法是什么?

【问题讨论】:

    标签: python python-3.x pandas


    【解决方案1】:

    这是一种利用broadcasting 检查两个数据帧之间是否相等并在结果上使用all 来检查所有行匹配位置的方法。然后我们可以从np.where 的结果中获得两个数据框列名的索引数组(@piR 的贡献):

    i, j = np.where((a.values[:,None] == b.values[:,:,None]).all(axis=0))
    dict(zip(a.columns[j], b.columns[i]))
    # {'a7': 'b2', 'a6': 'b3', 'a4': 'b4', 'a2': 'b7'}
    

    【讨论】:

    • 我对你的帖子嗤之以鼻。希望你不介意。请根据自己的喜好更改。
    • 嗯,相反 :) 不错的方法,并且检查大型数据帧它略微提高了性能@piRSquared
    【解决方案2】:

    这是使用sort_values的一种方式:

    m=df1.T.sort_values(by=[*df1.index]).index
    n=df2.T.sort_values(by=[*df2.index]).index
    d=dict(zip(m,n))
    print(d)
    

    {'a1': 'b5', 'a5': 'b1', 'a2': 'b7', 'a3': 'b6', 'a6': 'b3', 'a7': 'b2', 'a4': 'b4'}
    

    【讨论】:

    • 感谢您分享漂亮的命令 Anky,请您在 [*df1.index] 部分解释更多好吗?会很感激你,干杯。
    • @RavinderSingh13 当然,sort_values(by=..) 将列表作为参数,所以我在这里将索引解包为列表,您也可以使用 list(df1.index) 而不是 [*df1.index] :)
    【解决方案3】:

    merge的一种方式

    s=df1.T.reset_index().merge(df2.T.assign(match=lambda x : x.index))
    dict(zip(s['index'],s['match']))
    {'a1': 'b5', 'a2': 'b7', 'a3': 'b6', 'a4': 'b4', 'a5': 'b1', 'a6': 'b3', 'a7': 'b2'}
    

    【讨论】:

    • 我想我会添加另一个聪明的解决方案,结果发现它和你的一样(-:哎呀。
    【解决方案4】:

    字典理解

    使用列值的tuple 作为字典中的可散列键

    d = {(*t,): c for c, t in df2.items()}
    {c: d[(*t,)] for c, t in df1.items()}
    
    {'a1': 'b5',
     'a2': 'b7',
     'a3': 'b6',
     'a4': 'b4',
     'a5': 'b1',
     'a6': 'b3',
     'a7': 'b2'}
    

    以防万一我们没有完美的表示,我只为存在匹配的列生成字典。

    d2 = {(*t,): c for c, t in df2.items()}
    d1 = {(*t,): c for c, t in df1.items()}
    
    {d1[c]: d2[c] for c in {*d1} & {*d2}}
    
    {'a5': 'b1',
     'a2': 'b7',
     'a7': 'b2',
     'a6': 'b3',
     'a3': 'b6',
     'a1': 'b5',
     'a4': 'b4'}
    

    idxmax

    这近乎荒谬...不要真的这样做。

    {c: df2.T.eq(df1[c]).sum(1).idxmax() for c in df1}
    
    {'a1': 'b5',
     'a2': 'b7',
     'a3': 'b6',
     'a4': 'b4',
     'a5': 'b1',
     'a6': 'b3',
     'a7': 'b2'}
    

    【讨论】:

    • 这是怎么回事,我可以理解这些语句中的每个表达,但在我的脑海中却没有完全明白这里到底发生了什么?有点像国际象棋,我知道如何移动棋盘上的所有棋子,但看不到更多的棋子向前移动。
    • 好的...我现在已经消化了这个,它绝对简单,很棒。 +1
    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2020-12-03
    • 2019-11-10
    • 2014-10-03
    相关资源
    最近更新 更多