基于groupby的DataFrame过滤器

时间:2017-07-12 15:03:58

标签: python pandas pandas-groupby

这是我的简化示例df:

      salesPerson customer measure timeStamp
      --------------------------------------
      A           123      I       12:30
      A           123      II      12:30
      A           123      III     12:30
      B           123      IV      12:35
      C           456      I       14:30
      C           456      II      14:30
      D           456      III     14:15

我想做什么,它要提交数据框,如果2个不同的salesPerson Id拥有相同的客户编号,请保留salesSerson的所有行,而timeStamp是最早的。在这个例子中得到的df是:

      salesPerson customer measure timeStamp
      --------------------------------------
      A           123      I       12:30
      A           123      II      12:30
      A           123      III     12:30
      D           456      III     14:15

最好/最pythonic的方法是什么?我想过使用pandas groupby.filter或groupby.transform,但坦率地说不知道如何准确地编写它们。

奖励积分是将已删除的行放在单独的deleted_df对象中。

1 个答案:

答案 0 :(得分:2)

这个单行应该可以解决问题:

df[df['salesPerson'].isin(df.iloc[df.groupby(['customer'])['timeStamp'].idxmin(), 'salesPerson'])]

<强>解释

要确定要过滤的销售人员,请先按dfcustomer进行分组,然后使用timeStamp获取找到最低idxmin的索引:

df.groupby(['customer'])['timeStamp'].idxmin()

然后,将这些索引值与我们想要的列一起传递给iloc,以获取我们将用于过滤的salesPerson值:

df.iloc[df.groupby(['customer'])['timeStamp'].idxmin(), 'salesPerson']

最后,将该结果传递给Series方法isin,并使用该方法索引到df。结果是:

0  A  123    I 2017-07-12 12:30:00
1  A  123   II 2017-07-12 12:30:00
2  A  123  III 2017-07-12 12:30:00
6  D  456  III 2017-07-12 14:15:00

要使用已过滤的行创建第二个DataFrame,您可以将索引从已过滤的df传递到原始df并排除这些行。因此,如果我们将上述结果分配给df1,我们可以通过以下方式创建补充df2

df2 = df[~df.index.isin(df1.index)]

结果:

3  B  123  IV 2017-07-12 12:35:00
4  C  456   I 2017-07-12 14:30:00
5  C  456  II 2017-07-12 14:30:00