【问题标题】:Performing joins in Pandas在 Pandas 中执行连接
【发布时间】:2018-05-05 20:11:14
【问题描述】:

我熟悉在 pandas 中执行 join

pd.merge(A,B,on='key',how='inner')

但是我如何在 Pandas 中为这 3 个给定的连接编写查询,因为它们需要 IF NULL

【问题讨论】:

    标签: python sql database pandas


    【解决方案1】:

    设置

    A = pd.DataFrame(dict(key=range(0, 5), col1=list('abcde')))
    B = pd.DataFrame(dict(key=range(2, 7), col2=list('vwxyz')))
    
    print(A, B, sep='\n' * 2)
    
      col1  key
    0    a    0
    1    b    1
    2    c    2
    3    d    3
    4    e    4
    
      col2  key
    0    v    2
    1    w    3
    2    x    4
    3    y    5
    4    z    6
    

    使用pd.DataFrame.merge

    最直接的方法是使用indicator 参数。

    A.merge(B, 'outer', indicator=True)
    
      col1  key col2      _merge
    0    a    0  NaN   left_only
    1    b    1  NaN   left_only
    2    c    2    v        both
    3    d    3    w        both
    4    e    4    x        both
    5  NaN    5    y  right_only
    6  NaN    6    z  right_only
    

    那么我们可以使用pd.DataFrame.query

    A - B

    A.merge(B, 'outer', indicator=True).query('_merge == "left_only"')
    
      col1  key col2     _merge
    0    a    0  NaN  left_only
    1    b    1  NaN  left_only
    

    B - A

    A.merge(B, 'outer', indicator=True).query('_merge == "right_only"')
    
      col1  key col2      _merge
    5  NaN    5    y  right_only
    6  NaN    6    z  right_only
    

    对称差分

    A.merge(B, 'outer', indicator=True).query('_merge != "both"')
    
      col1  key col2      _merge
    0    a    0  NaN   left_only
    1    b    1  NaN   left_only
    5  NaN    5    y  right_only
    6  NaN    6    z  right_only
    

    使用pd.Series.isin(大部分)

    但是,我想简单地使用 pd.Series.isin 作为布尔掩码。

    A - B

    A[~A.key.isin(B.key)]
    
      col1  key
    0    a    0
    1    b    1
    

    B - A

    B[~B.key.isin(A.key)]
    
      col2  key
    3    y    5
    4    z    6
    

    对称差分

    A[~A.key.isin(B.key)].append(B[~B.key.isin(A.key)])
    

    或者

    A.append(B).drop_duplicates('key', keep=False)
    
      col1 col2  key
    0    a  NaN    0
    1    b  NaN    1
    3  NaN    y    5
    4  NaN    z    6
    

    【讨论】:

      【解决方案2】:

      虽然 piRSquared 的回答非常好,但这是另一种方法:

      import pandas as pd
      

      创建数据帧AB

      A = pd.DataFrame({'key': range(1, 6), 'A': ['a'] * 5})
      B = pd.DataFrame({'key': range(3, 8), 'B': ['b'] * 5})
      

      示例 A 的解决方案(即左不包括连接): 首先执行左连接,然后只保留A 中在B 中没有对应行的列:

      pd.merge(A, B, on = 'key', how = 'left')[~A.key.isin(B.key)]
      
        key   A   B
      0   1   a   NaN
      1   2   a   NaN
      

      例如 B 的解决方案(即右排除连接): 与解决方案 A 非常相似,但具有右连接:

      pd.merge(A, B, on = 'key', how = 'right')[~B.key.isin(A.key)]
          key A   B
      3   6   NaN b
      4   7   NaN b
      

      例如 C 的解决方案(即外部不包括连接): 首先执行全外连接:

      outer = pd.merge(A, B, on = 'key', how = 'outer')
      

      然后过滤AB中在BA中没有对应键的行:

      outer[outer.key.isin(list(A.key[~A.key.isin(B.key)]) + list(B.key[~B.key.isin(A.key)]))]
      
         key  A   B
      0   1   a   NaN
      1   2   a   NaN
      5   6   NaN b
      6   7   NaN b
      

      【讨论】:

        猜你喜欢
        • 2014-06-23
        • 1970-01-01
        • 2019-10-01
        • 2015-02-15
        • 2021-02-14
        • 1970-01-01
        • 1970-01-01
        • 2019-10-18
        相关资源
        最近更新 更多