【问题标题】:Outer Join on dataframes python数据框python上的外部连接
【发布时间】:2020-09-23 17:08:06
【问题描述】:

我似乎找到了LEFT JOIN vs. LEFT OUTER JOIN in SQL Serverhttps://chrisalbon.com/python/data_wrangling/pandas_join_merge_dataframe/,但还没有找到我要找的东西。我有两个 python 数据框:

A = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6]]),
                   columns=['a', 'b', 'c'])

    a   b   c
0   1   2   3
1   4   5   6
2   1   2   3
3   4   5   6

B = pd.DataFrame(np.array([[7, 8, 9], [7, 8, 9], [3, 2, 1], [3, 2, 1]]),
                   columns=['c', 'b', 'a'])

    c   b   a
0   7   8   9
1   7   8   9
2   3   2   1
3   3   2   1

其中值 [1, 2, 3] 在两者中重复,但 [4, 5, 6] 和 [9, 8, 7] 不重复。

我希望它具有来自一个数据帧但不加入另一个数据帧的所有值。例如:

A some_left_outer_join B = C

C = pd.DataFrame(np.array([ [4, 5, 6], [4, 5, 6]]),
                   columns=['a', 'b', 'c'])

并获得两个数据帧中不加入另一个数据帧的所有值。例如:

A some_outer_join B = D

D = pd.DataFrame(np.array([ [4, 5, 6], [4, 5, 6] , [9, 8, 7] , [9, 8, 7]]),
                   columns=['a', 'b', 'c'])

尝试

 (pd.merge(left=A, right=B, how='left', on=['a', 'b', 'c']))

    a   b   c
0   1   2   3
1   1   2   3
2   4   5   6
3   1   2   3
4   1   2   3
5   4   5   6

给我加入和未加入的元素。我只想要未加入的元素。请问,我怎样才能得到渴望的元素?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您可以将参数indicator=True 与外部连接一起使用,然后通过boolean indexing 过滤Series.eq 用于==Series.ne 用于!=

    df = (pd.merge(left=A, right=B, how='outer', on=['a', 'b', 'c'], indicator=True))
    print (df)
       a  b  c      _merge
    0  1  2  3        both
    1  1  2  3        both
    2  1  2  3        both
    3  1  2  3        both
    4  4  5  6   left_only
    5  4  5  6   left_only
    6  9  8  7  right_only
    7  9  8  7  right_only
    
    C = df[df['_merge'].eq('left_only')]
    print (C)
       a  b  c     _merge
    4  4  5  6  left_only
    5  4  5  6  left_only
    
    D = df[df['_merge'].ne('both')]
    print (D)
       a  b  c      _merge
    4  4  5  6   left_only
    5  4  5  6   left_only
    6  9  8  7  right_only
    7  9  8  7  right_only
    

    如果还想删除列:

    s = df.pop('_merge')
    C = df[s.eq('left_only')]
    print (C)
       a  b  c
    4  4  5  6
    5  4  5  6
    
    D = df[s.ne('both')]
    print (D)
       a  b  c
    4  4  5  6
    5  4  5  6
    6  9  8  7
    7  9  8  7
    

    【讨论】:

    • 这太棒了!,是正确的答案,谢谢! .但是让我问一下,有没有一种内存更有效的方法来做到这一点? ,在超大数据帧上(超过一百万行,内存非常昂贵)
    【解决方案2】:

    一个技巧是在 A 和 B 中添加一个虚拟列。因此,在不匹配的行中,您将在虚拟列中获得 NaN。您可以稍后删除虚拟列

    B['d'] = 0
    A['e'] = 0
    AB = pd.merge(left=A, right=B, how='outer', on=['a', 'b', 'c'])
    C = AB[AB.d.apply(pd.isnull)]
    D = AB[(AB.d.apply(pd.isnull)) | (AB.e.apply(pd.isnull))]
    
    C
    
        a   b   c   e   d
    4   4   5   6   0.0 NaN
    5   4   5   6   0.0 NaN
    
    D
        a   b   c   e   d
    4   4   5   6   0.0 NaN
    5   4   5   6   0.0 NaN
    6   9   8   7   NaN 0.0
    7   9   8   7   NaN 0.0
    

    【讨论】:

      猜你喜欢
      • 2021-07-24
      • 2021-07-29
      • 2017-05-20
      • 1970-01-01
      • 1970-01-01
      • 2015-11-16
      • 2021-04-20
      • 2012-01-08
      • 2023-01-03
      相关资源
      最近更新 更多