我有一个形式的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个事件)。
我认为我需要在执行当前代码之前先执行此操作,但是我不确定该如何处理。
一些注意事项:
答案 0 :(得分:2)
此处需要进行一些工作,使用diff
和cumsum
创建子组,如果继续,则它们属于一个组,并选择每个子组的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'))