Python 熊猫在每组中获得最多的n项记录

Python 熊猫在每组中获得最多的n项记录,python,pandas,greatest-n-per-group,window-functions,top-n,Python,Pandas,Greatest N Per Group,Window Functions,Top N,假设我有如下数据帧: >>> df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]}) >>> df id value 0 1 1 1 1 2 2 1 3 3 2 1 4 2 2 5 2 3 6 2 4 7 3 1 8 4 1 id

假设我有如下数据帧:

>>> df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]})
>>> df
   id  value
0   1      1
1   1      2
2   1      3
3   2      1
4   2      2
5   2      3
6   2      4
7   3      1
8   4      1
   id  value
0   1      1
1   1      2
3   2      1
4   2      2
7   3      1
8   4      1
我想获得一个新的数据帧,每个id有前2条记录,如下所示:

>>> df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]})
>>> df
   id  value
0   1      1
1   1      2
2   1      3
3   2      1
4   2      2
5   2      3
6   2      4
7   3      1
8   4      1
   id  value
0   1      1
1   1      2
3   2      1
4   2      2
7   3      1
8   4      1
我可以通过以下方式对一组又一组的记录进行编号:

>>> dfN = df.groupby('id').apply(lambda x:x['value'].reset_index()).reset_index()
>>> dfN
   id  level_1  index  value
0   1        0      0      1
1   1        1      1      2
2   1        2      2      3
3   2        0      3      1
4   2        1      4      2
5   2        2      5      3
6   2        3      6      4
7   3        0      7      1
8   4        0      8      1
>>> dfN[dfN['level_1'] <= 1][['id', 'value']]
   id  value
0   1      1
1   1      2
3   2      1
4   2      2
7   3      1
8   4      1
dfN=df.groupby('id').apply(lambda x:x['value'].reset_index()).reset_index() >>>dfN id级别_1索引值 0 1 0 0 1 1 1 1 1 2 2 1 2 2 3 3 2 0 3 1 4 2 1 4 2 5 2 2 5 3 6 2 3 6 4 7 3 0 7 1 8 4 0 8 1
>>>dfN[dfN['level_1']您是否尝试了
df.groupby('id')。head(2)

生成的输出:

>>> df.groupby('id').head(2)
       id  value
id             
1  0   1      1
   1   1      2 
2  3   2      1
   4   2      2
3  7   3      1
4  8   4      1
(请记住,根据您的数据,您可能需要在之前进行订购/排序)

编辑:如提问者所述,使用
df.groupby('id').head(2).重置索引(drop=True)
删除多重索引并展平结果

>>> df.groupby('id').head(2).reset_index(drop=True)
    id  value
0   1      1
1   1      2
2   2      1
3   2      2
4   3      1
5   4      1
,您现在可以对
groupby
对象执行
nlargest
nsmalest

In [23]: df.groupby('id')['value'].nlargest(2)
Out[23]: 
id   
1   2    3
    1    2
2   6    4
    5    3
3   7    1
4   8    1
dtype: int64
有一点奇怪的是,你在那里也得到了原始索引,但这可能真的很有用,这取决于你的原始索引是什么

如果你对它不感兴趣,你可以做
.reset\u index(level=1,drop=True)
来彻底摆脱它


(注意:您也可以在DataFrameGroupBy上执行此操作,但目前它仅适用于
系列
系列GroupBy

有时提前排序整个数据非常耗时。 我们可以先分组,然后为每组进行topk:

g = df.groupby(['id']).apply(lambda x: x.nlargest(topk,['value'])).reset_index(drop=True)
  • 这里的排序值升序为false,与nlargest相似,为True,与nsmallest相似
  • head中的值与我们在nlargest中给出的值相同,以获得每个组要显示的值的数量
  • 重置索引是可选的,不是必需的

是的,我想就是这样。不知何故忽略了这一点。你知道对组内记录进行编号的好方法吗?为了获得所需的输出,我还添加了
。reset\u index(drop=True)
刚刚被合并;将在0.13中,新方法称为
cumcount
(对每组中的记录进行编号)为了让@dorvak的答案更完整,如果你想得到每个
id
的两个最小值,那么就做
df.sort\u值(['id','value'],axis=0)。groupby('id')。head(2)
。另一个例子是,每个
id
的最大值由
df.sort\u值(['id','value'],axis=0)。groupby('id')。tail(1)
。从0.23.4开始,
df.groupby('id').head(2)
之后不需要展平。可能重复的“top-n”并不意味着“最上面的n行/第一行/头行”,就像您正在寻找的那样!它意味着“具有最大值的n行”。有办法获得
唯一的\u限制(n)
?就像我想要前n个唯一值一样?如果我要求
nlargest
它将对整个df进行排序,这可能会花费很多钱。这不适用于在groupby上进行聚合的情况?例如,
df.groupby([pd.Grouper(freq='M'),'A'])['B'].count().nlargest(5,'B')
这只是返回整个系列中的前5名,而不是每个组。现在在
DataFrameGroupBy
s上也可以这样做的声明似乎是错误的,链接的拉取请求似乎只将
nlargest
添加到simple
DataFrame
s。这很不幸,因为如果您想选择不止一列?