【问题标题】:only outer join python pandas只外连接 python pandas
【发布时间】:2018-04-20 09:06:20
【问题描述】:

我有两个具有相同列名的 DataFrame,其中包含一些匹配的数据和一些唯一的数据。

我想排除中间,只保存两个 DataFrame 独有的内容。

我将如何连接、合并或加入这两个数据框来做到这一点?

例如在这张图片中,我不想要这张图片的中间,我想要两边而不是中间:

这是我现在的代码:

def query_to_df(query):
    ...
    df_a = pd.DataFrame(data_a)
    df_b = pd.DataFrame(data_b)
    outer_results = pd.concat([df_a, df_b], axis=1, join='outer')
    return df

让我举个例子说明我需要什么:

df_a = 
col_a  col_b  col_c
   a1     b1     c1
   a2     b2     c2

df_b = 
col_a  col_b  col_c
   a2     b2     c2
   a3     b3     c3

# they only share the 2nd row:    a2     b2     c2 
# so the outer result should be:
col_a  col_b  col_c  col_a  col_b  col_c
   a1     b1     c1     NA     NA     NA
   NA     NA     NA     a3     b3     c3

或者我也会对 2 个数据框感到满意

result_1 =
col_a  col_b  col_c
   a1     b1     c1

result_2 =
col_a  col_b  col_c
   a3     b3     c3

最后,您会注意到 a2 b2 c2 被排除在外,因为所有列都匹配 - 我如何指定要根据所有列加入,而不仅仅是 1?如果df_aa2 foo c2,我也希望该行也在result_1 中。

【问题讨论】:

  • 我认为您正在寻找pd.merge 而不是pd.concat。实际上,不太清楚你是如何合并的......我认为更准确的描述是你得到的行只存在于一个表中。即使那样,我也不确定你为什么将它们并排放置,因为现在你有 2 个 col_acol_bcol_c

标签: python pandas dataframe outer-join


【解决方案1】:

concat 和 drop_duplicates with keep = False

new_df = pd.concat([df_a, df_b]).drop_duplicates(keep=False)

    col_a   col_b   col_c
0   a1      b1      c1
1   a3      b3      c3

使用 numpy setdiff1

df_a = pd.DataFrame(np.setdiff1d(np.array(df_a.values), np.array(df_b.values))\
.reshape(-1, df_a.shape[1]), columns = df_a.columns)

df_b = pd.DataFrame(np.setdiff1d(np.array(df_b.values), np.array(df_a.values))\
.reshape(-1, df_b.shape[1]), columns = df_b.columns)

df_a

    col_a   col_b   col_c
0   a1      b1      c1

df_b

    col_a   col_b   col_c
0   a3      b3      c3

【讨论】:

    【解决方案2】:

    使用pd.DataFrame.drop_duplicates
    这假设行在其各自的数据框中是唯一的。

    df_a.append(df_b).drop_duplicates(keep=False)
    
      col_a col_b col_c
    0    a1    b1    c1
    1    a3    b3    c3
    

    您甚至可以将pd.concatkeys 参数一起使用来给出行所在的上下文。

    pd.concat([df_a, df_b], keys=['a', 'b']).drop_duplicates(keep=False)
    
        col_a col_b col_c
    a 0    a1    b1    c1
    b 1    a3    b3    c3
    

    【讨论】:

    • 我看到了。这很聪明!
    【解决方案3】:

    使用mergeindicator 参数和outer 先加入,然后按queryboolean indexing 过滤:

    df = df_a.merge(df_b, how='outer', indicator=True)
    print (df)
      col_a col_b col_c      _merge
    0    a1    b1    c1   left_only
    1    a2    b2    c2        both
    2    a3    b3    c3  right_only
    
    a = df.query('_merge == "left_only"').drop('_merge', 1)
    print (a)
      col_a col_b col_c
    0    a1    b1    c1
    
    b = df.query('_merge == "right_only"').drop('_merge', 1)
    print (b)
      col_a col_b col_c
    2    a3    b3    c3
    

    或者:

    a = df[df['_merge'] == "left_only"].drop('_merge', 1)
    print (a)
      col_a col_b col_c
    0    a1    b1    c1
    
    b = df[df['_merge'] == "right_only"].drop('_merge', 1)
    print (b)
      col_a col_b col_c
    2    a3    b3    c3
    

    【讨论】:

      猜你喜欢
      • 2016-10-07
      • 2018-09-05
      • 1970-01-01
      • 2018-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-19
      • 2023-04-07
      相关资源
      最近更新 更多