【问题标题】:Drop rows and sort one dataframe according to another删除行并根据另一个数据框对一个数据框进行排序
【发布时间】:2020-10-25 04:35:12
【问题描述】:

我有两个 pandas 数据框(df1df2):

# df1
  ID  COL
   1    A
   2    F
   2    A
   3    A
   3    S
   3    D
   4    D

# df2
  ID  VAL
   1    1
   2    0
   3    0
   3    1
   4    0

我的目标是将df2 中的相应val 附加到df1 中的每个ID。但是,这种关系不是一对一的(这是我客户的错,对此我无能为力)。为了解决这个问题,我想通过df2['ID']df1 进行排序,使得df1['ID']df2['ID'] 相同。

所以基本上,对于 0 到 len(df2) 中的任何行 i

  • 如果df1.loc[i, 'ID'] == df2.loc[i, 'ID'] 则在df1 中保留行i
  • 如果 df1.loc[i, 'ID'] != df2.loc[i, 'ID'] 则从 df1 删除行 i 并重复。

想要的结果是:

  ID  COL
   1    A
   2    F
   3    A
   3    S
   4    D

这样,我可以使用pandas.concat([df1, df2['ID']], axis=0)df2[VAL] 分配给df1

有没有标准化的方法来做到这一点? pandas.merge() 有没有办法做到这一点?

在此被投票为重复之前,请注意len(df1) != len(df2),所以threads like this 并不是我想要的。

【问题讨论】:

    标签: python pandas dataframe sorting


    【解决方案1】:

    这可以通过合并ID 和每个ID 中的顺序来完成:

    (df1.assign(idx=df1.groupby('ID').cumcount())
        .merge(df2.assign(idx=df2.groupby('ID').cumcount()),
               on=['ID','idx'],
               suffixes=['','_drop'])
        [df1.columns]
    )
    

    输出:

       ID COL
    0   1   A
    1   2   F
    2   3   A
    3   3   S
    4   4   D
    

    【讨论】:

      【解决方案2】:

      我能看到的获得所需结果的最简单方法是:

      # Add a count for each repetition of the ids to temporary frames
      x = df1.assign(id_counter=df1.groupby('ID').cumcount())
      y = df2.assign(id_counter=df2.groupby('ID').cumcount())
      
      # Merge using the ID and the repetition counter
      df1 = pd.merge(x, y, how='right', on=['ID', 'id_counter']).drop('id_counter', axis=1)
      

      这会产生这个输出:

          ID  COL VAL
      0   1   A   1
      1   2   F   0
      2   3   A   0
      3   3   S   1
      4   4   D   0
      

      【讨论】:

      • @ScottBoston 很相似,不同的是输出的额外列,这是原问题末尾需要的下一步。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-04
      • 2018-06-22
      • 2018-01-16
      • 1970-01-01
      • 2021-01-24
      • 2019-02-04
      • 1970-01-01
      相关资源
      最近更新 更多