【问题标题】:How to join pandas dataframe on 2 columns?如何在 2 列上加入熊猫数据框?
【发布时间】:2021-09-16 07:03:19
【问题描述】:

假设以下 DataFrames

df1:

id    data1
1     10
2     200
3     3000
4     40000

df2:

id1    id2    data2
1      2      210
1      3      3010
1      4      40010
2      3      3200
2      4      40200
3      4      43000

我想要新的 df3:

id1    id2    data2    data11    data12        
1      2      210      10        200
1      3      3010     10        3000
1      4      40010    10        40000 
2      3      3200     200       3000
2      4      40200    200       40000
3      4      43000    3000      40000

在 pandas 中实现这一目标的正确方法是什么?


编辑:请不要具体数据可以任意。我选择这个特定数据只是为了显示所有内容的来源,但每个数据元素都与任何其他数据元素没有关联。


其他数据框示例,因为第一个不够清楚:

df4:

id    data1
1     a
2     b
3     c
4     d

df5:

id1    id2    data2
1      2      e
1      3      f
1      4      g
2      3      h
2      4      i
3      4      j

我想要新的 df6:

id1    id2    data2    data11    data12        
1      2      e        a         b  
1      3      f        a         c
1      4      g        a         d
2      3      h        b         c
2      4      i        b         d
3      4      j        c         d

编辑2: Data11 和Data12 只是data1 的一个副本,对应的id 为id1id2

【问题讨论】:

  • 您需要说明data12 是如何从您的数据框生成的。
  • @Gulzar data12 是第一个数据帧的 id 和第二个数据帧的 id2 之间连接的结果,对吧?
  • @cody 如果我知道如何在 pandas 中正确执行连接,您将不会看到这个问题。请参阅edit2,我认为它回答了您的问题
  • 好的。知道了。查看我的编辑。
  • 嗨@Gulzar 我理解你的问题并根据要求编辑了我的答案。可能会有所帮助

标签: python pandas


【解决方案1】:

1.首先使用 id1 和 id 列合并两个数据框
2.将data1重命名为data11
3. 删除 id 列
4.现在在id2和id上合并df1和df3

df3 = pd.merge(df2,df1,left_on=['id1'],right_on=['id'],how='left')
df3.rename(columns={'data1':'data11'},inplace=True)
df3.drop('id',axis=1,inplace=True)

df3 = pd.merge(d3,df1,left_on=['id2'],right_on=['id'],how='left')
df3.rename(columns={'data1':'data12'},inplace=True)
df3.drop('id',axis=1,inplace=True)

希望能解决你的问题

【讨论】:

  • 谢谢!至于减法,我将进行编辑以明确数据恰好完全适合明显的计算。从理论上讲,它可以是任何数据。我想说明这个例子
  • 但它没有回答我的问题,请参阅编辑。第 4 行的计算不适用于任意数据
  • @Gulzar 你想减去 data2 和 data11 吗?
  • @Gulzar 请说清楚什么是data12? data11 是来自 df1 的列,而 data12 似乎是减法,这就是我应用减​​法的原因
【解决方案2】:

试试这个:

# merge dataframes, first on id and id1 then on id2
df3 = pd.merge(df1, df2, left_on="id", right_on="id1", how="inner")
df3 = pd.merge(df1, df3, left_on="id", right_on="id2", how="inner")

# rename and reorder columns
cols = [ 'id1', 'id2', 'data2', 'data1_y', 'data1_x']
df3 = df3[cols]

new_cols = ["id1", "id2", "data2", "data11", "data12"]
df3.columns = new_cols

df3.sort_values("id1", inplace=True)

print(df3)

打印出来:

    id1 id2 data2   data11  data12
0   1   2   210     10      200
1   1   3   3010    10      3000
2   1   4   40010   10      40000
3   2   3   3200    200     3000
4   2   4   40200   200     40000
5   3   4   43000   3000    40000

【讨论】:

    【解决方案3】:

    解决您的问题的方法之一是:

    data1 = {'id' : [1,2,3,4],
             'data1' : [10,200,3000,40000]}
    
    data2 = {'id1' : [1,1,1,2,2,3],
             'id2' : [2,3,4,3,4,4],
             'data2' : [210,3010,40010,3200,40200,43000]}
    
    df1 = pd.DataFrame(data1)
    df2 = pd.DataFrame(data2)
    
    df1:
    id    data1
    1     10
    2     200
    3     3000
    4     40000
    
    df2:
    id1    id2    data2
    1      2      210
    1      3      3010
    1      4      40010
    2      3      3200
    2      4      40200
    3      4      43000
    
    df3 = df2.set_index('id1').join(df1.set_index('id'))
    df3.index.names = ['id1']
    df3.reset_index(inplace=True)
    
    final = df3.set_index('id2').join(df1.set_index('id'), rsuffix='2')
    final.index.names = ['id2']
    final.reset_index(inplace=True)
    
    final[['id1','id2','data2','data1','data12']].sort_values('id1')
    
    output df: 
    
    id1 id2 data2   data1   data12
     1   2    210    10     200
     1   3    3010   10     3000
     1   4    40010  10     40000
     2   3    3200   200    3000
     2   4    40200  200    40000
     3   4    43000  3000   40000
    

    我希望这会对你有所帮助。 ​

    【讨论】:

      【解决方案4】:

      在带有rangef-string 的for 循环中使用merge

      我们可以概括这一点并使其在拥有两个以上数据帧时更容易扩展的一种方法是使用list comprehension 和带有range 的for 循环。

      之后我们删除重复的列名:

      dfs = [df2.merge(df1, 
                       left_on=f'id{x+1}', 
                       right_on='id', 
                       how='left').rename(columns={'data1':f'data1{x+1}'}) for x in range(2)]
      
      df = pd.concat(dfs, axis=1).drop('id', axis=1)
      
      df = df.loc[:, ~df.columns.duplicated()]
      

      输出

         id1  id2  data2  data11  data12
      0    1    2    210      10     200
      1    1    3   3010      10    3000
      2    1    4  40010      10   40000
      3    2    3   3200     200    3000
      4    2    4  40200     200   40000
      5    3    4  43000    3000   40000
      

      【讨论】:

        【解决方案5】:

        正如@tawab_shakeel 之前提到的,您的主要步骤是根据某些(SQL)连接规则合并特定列上的数据框;只是为了让您了解合并特定列的不同方法,这里是一个一般指南。

        Joining Dataframes in Pandas

        SQL Join Types

        【讨论】:

          【解决方案6】:

          在列 id1 和 id2 上对数据框 df2 使用两个左手合并

          txt="""id,data1 1,一个 2,b 3,c 4,d """

          from io import StringIO
          f = StringIO(txt)
          df1 = pd.read_table(f,sep =',')
          df1['id']=df1['id'].astype(int)
          
          txt="""id1,id2,data2
          1,2,e
          1,3,f
          1,4,g
          2,3,h
          2,4,i
          3,4,j
          """
          
          f = StringIO(txt)
          df2 = pd.read_table(f,sep =',')
          df2['id1']=df2['id1'].astype(int)
          df2['id2']=df2['id2'].astype(int)
          
          left_on='id1'
          right_on='id'
          suffix='_1'
          df2=df2.merge(df1, how='left', left_on=left_on, right_on=right_on, 
                            suffixes=("", suffix))
          
          left_on='id2'
          right_on='id'
          suffix='_2'
          df2=df2.merge(df1, how='left', left_on=left_on, right_on=right_on, 
                            suffixes=("", suffix))
          
          print(df2)
          

          输出

             id1  id2 data2  id data1  id_2 data1_2
          0    1    2     e   1     a     2       b
          1    1    3     f   1     a     3       c
          2    1    4     g   1     a     4       d
          3    2    3     h   2     b     3       c
          4    2    4     i   2     b     4       d
          5    3    4     j   3     c     4       d
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-03-30
            • 2014-09-21
            • 1970-01-01
            • 2013-12-20
            • 2017-11-30
            • 2018-10-28
            • 1970-01-01
            相关资源
            最近更新 更多