这是我的简化示例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对象中。
答案 0 :(得分:2)
这个单行应该可以解决问题:
df[df['salesPerson'].isin(df.iloc[df.groupby(['customer'])['timeStamp'].idxmin(), 'salesPerson'])]
<强>解释强>
要确定要过滤的销售人员,请先按df
对customer
进行分组,然后使用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