基于groupby的DataFrame过滤器
DataFrame filter based on 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 个不同的销售人员 ID 具有相同的客户编号,则保留时间戳最早的销售人员的所有行。此示例中的结果 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
best/most pythonic 的方法是什么?我考虑过使用 pandas groupby.filter 或 groupby.transform,但坦率地说不知道如何准确地写这些。
奖励积分是将删除的行放在单独的 deleted_df 对象中。
这条单线应该可以解决问题:
df[df['salesPerson'].isin(df.iloc[df.groupby(['customer'])['timeStamp'].idxmin(), 'salesPerson'])]
解释:
要确定我们要筛选的销售人员,首先将 df
按 customer
分组,然后使用 idxmin
获取找到最小值 timeStamp
的索引:
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
这是我的简化示例 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 个不同的销售人员 ID 具有相同的客户编号,则保留时间戳最早的销售人员的所有行。此示例中的结果 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
best/most pythonic 的方法是什么?我考虑过使用 pandas groupby.filter 或 groupby.transform,但坦率地说不知道如何准确地写这些。
奖励积分是将删除的行放在单独的 deleted_df 对象中。
这条单线应该可以解决问题:
df[df['salesPerson'].isin(df.iloc[df.groupby(['customer'])['timeStamp'].idxmin(), 'salesPerson'])]
解释:
要确定我们要筛选的销售人员,首先将 df
按 customer
分组,然后使用 idxmin
获取找到最小值 timeStamp
的索引:
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