【问题标题】:merge dataframes based on column A OR B基于列 A 或 B 合并数据框
【发布时间】:2021-09-08 13:56:14
【问题描述】:

我需要合并两个数据框,但可以在右侧数据框的任意两列上进行合并。

df_1 = pd.DataFrame({'col' : ['a', 'b', 'c']})
df_2 = pd.DataFrame({'col_a' : ['a', 'b', np.nan], 'col_b' : ['z', np.nan, 'c']})
df_1.merge(df_2, how = 'left', left_on = 'col', right_on = 'col_a')

在上面的示例中,合并正在寻找col == 'a'col == 'b' 的匹配项,因为df_2 在其col_a 列中包含这些值。但我也希望它能找到与df_2col_b == 'c' 匹配。如果正则表达式与合并一起使用,一个好的解决方案应该是这样的:

df_1.merge(df_2, how = 'left', left_on = 'col', right_on = 'col_a|col_b')

输出应如下所示:

col col_a   col_b
a    a      z
b    b      NaN
c    NaN    c

有什么想法吗?

【问题讨论】:

    标签: python pandas merge


    【解决方案1】:

    我相信我们在这里寻找的是合并两次,连接结果并删除可能因col_acol_b 相同而导致的任何重复项。

    import numpy as np
    import pandas as pd
    
    df_1 = pd.DataFrame({'col' : ['a', 'c', 'b']})
    df_2 = pd.DataFrame({'col_a' : ['b', np.nan, 'a', 'a', 'c'], 'col_b' : [np.nan, 'c', 'z', 'b', 'c']})
    
    df = (
        pd.concat([
            df_1.merge(df_2, left_on='col', right_on='col_a'),
            df_1.merge(df_2, left_on='col', right_on='col_b'),
        ]).drop_duplicates()
        .reset_index(drop=True)
    )
    
    print(df)
    #   col col_a col_b
    # 0   a     a     z
    # 1   a     a     b
    # 2   c     c     c
    # 3   b     b   NaN
    # 4   c   NaN     c
    # 5   b     a     b
    

    我们看到我们处理:

    1. a 匹配 col_a 两次
    2. b 分别匹配 col_acol_b(包括匹配 a 的行)
    3. c 同时匹配 col_acol_b,但在输出中不重复。

    【讨论】:

      【解决方案2】:

      您可以执行两个合并并使用combine_first 来融合两个合并:

      (df_1.merge(df_2, left_on='col', right_on='col_a', how='left')
           .combine_first(df_1.merge(df_2, left_on='col', right_on='col_b', how='left'))
      )
      

      输出:

        col col_a col_b
      0   a     a     z
      1   b     b   NaN
      2   c   NaN     c
      

      其他示例(没有已对齐索引的缺陷):

      df_1 = pd.DataFrame({'col' : ['a', 'c', 'b']})
      df_2 = pd.DataFrame({'col_a' : ['b', np.nan, 'a'], 'col_b' : [np.nan, 'c', 'z']})
      

      输出:

        col col_a col_b
      0   a     a     z
      1   c   NaN     c
      2   b     b   NaN
      

      【讨论】:

      • 如果任一合并是一对一的,例如如果df_2col_a 中有两次a?那combine_first不会有麻烦吗?此外,我们应该删除col_acol_bNaN 的行。
      • @KyleParsons 在这种情况下,我们需要 OP 来定义如何合并的规则,因为它不是微不足道的,所以我认为这不是一个约束,但你是对的 ;)
      【解决方案3】:

      避免根据你的输出尝试加入

       df_1.join(df_2)
      

      输出

      col col_a   col_b
      0   a   a   z
      1   b   b   NaN
      2   c   NaN c
      

      或者

      df_1.merge(df_2, how='left', left_on='col', right_on='col_a').combine_first(df_2)
      

      输出

      col col_a col_b
      0   a     a     z
      1   b     b   NaN
      2   c   NaN     c
      

      【讨论】:

      • 这只是偶然的,因为索引已经对齐。试试df_2 = pd.DataFrame({'col_a' : ['b', np.nan, 'a'], 'col_b' : [np.nan, 'c', 'z']})
      • 不,它没有,因为combine_first 也可以基于索引工作;)
      • 尝试df_1 = pd.DataFrame({'col' : ['a', 'c', 'b']}) ; df_2 = pd.DataFrame({'col_a' : ['b', np.nan, 'a'], 'col_b' : [np.nan, 'c', 'z']}),输出不正确(z 将在b 行结束)
      猜你喜欢
      • 2023-01-07
      • 1970-01-01
      • 1970-01-01
      • 2018-01-30
      • 2015-01-17
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 1970-01-01
      相关资源
      最近更新 更多