有条件的最小熊猫

时间:2019-12-12 16:24:50

标签: python pandas

我有一个形式的df(只是一个样本):

Name     Event    Score
Joe      1        0.9
Tim      8        0.4
Ben      3        0.7
Ben      9        0.1
Tim      2        0.6
Ben      5        1.1
Joe      2        1.2
Tim      6        0.9
Tim      3        0.7
Joe      7        0.6
Joe      6        0.8

我的第一步是分组,并为每个人选择2个最小的分数。我可以使用以下代码做到这一点:

top_2 = df.groupby('Name')['Score'].apply(lambda x: x.nsmallest(2)).reset_index('Name')
df = df[(df.index.isin(top_2.index))].reset_index(drop=True)

给出的结果:

Name     Event    Score
Tim      8        0.4
Ben      3        0.7
Ben      9        0.1
Tim      2        0.6
Joe      7        0.6
Joe      6        0.8

但是,现在我要确保每个人都没有连续的事件。例如,乔有事件6和7。相反,我想选择事件7(因为它小于6)和事件1(乔的下一个最小事件,因此他仍然有2个事件)。

我认为我需要在执行当前代码之前先执行此操作,但是我不确定该如何处理。

一些注意事项:

  • 一个人的活动不会重复
  • 名字是唯一的
  • 原始数据中某人的事件数可以在任何地方> 1

2 个答案:

答案 0 :(得分:2)

此处需要进行一些工作,使用diffcumsum创建子组,如果继续,则它们属于一个组,并选择每个子组的min,然后,输出,我们选择两个中的最小值

df=df.sort_values(['Name','Event'])
s=df.groupby('Name')['Event'].apply(lambda x : x.diff().ne(1).cumsum())
newdf=df.groupby([df.Name,s]).apply(lambda x : x.nsmallest(1,'Score'))
newdf=newdf.sort_values('Score').groupby(newdf['Name']).head(2).reset_index(drop=True)
newdf
  Name  Event  Score
0  Ben      9    0.1
1  Tim      8    0.4
2  Joe      7    0.6
3  Tim      2    0.6
4  Ben      3    0.7
5  Joe      1    0.9

答案 1 :(得分:0)

按以下说明丢弃连续的重复项: Pandas: Drop consecutive duplicates 这是预处理处理步骤。

a = df['Name']

# mask duplicates 
mask = (a.shift(-1) == a) | (a.shift(1) == a)
# mask the head of each duplicated group including 1-element group
mask_head = (mask & (a.shift(1) != a)) | ~mask
df['dupl_id'] = np.NaN
# set id of each group as index of the head
df.loc[mask_head, 'dupl_id'] = df[mask_head].index
# set the same id for the whole group
df.loc[mask, 'dupl_id'] = df.loc[mask, 'dupl_id'].ffill()

df = df.sort_values(['Name', 'Score']).groupby('dupl_id').apply(lambda g: g.drop_duplicates('Name', keep='first'))
相关问题