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
添加到simpleDataFrame
s。这很不幸,因为如果您想选择不止一列?