Pandas根据条件返回最小值

3

我有一个如下形式的数据框(仅供参考):

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

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

我认为我需要在当前代码之前执行此步骤,但我不确定如何处理。

几个注意事项:

  • 对于一个人来说,事件不会重复
  • 姓名是唯一的
  • 原始数据中一个人的事件数量可能是任意大于1的数字

那么如果Andy有事件6, 7, 8,你会选择最小的并放弃其他两个吗? - Quang Hoang
他可能在6、8,但不在6、7或7、8。 - Bill K
2个回答

2

这里需要做一些工作,使用diffcumsum创建子组。如果它们是连续的,则属于同一组,并选择每个子组的最小值。然后,在输出中选择两者的最小值。

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

0

根据此处所述的方法删除连续重复项: Pandas: 删除连续重复项 这是预处理步骤。

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'))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接