假设我有这样的PandasDataFrame:
df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4], 'value':[1,2,3,1,2,3,4,1,1]})
它看起来像:
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
我想得到一个新的DataFrame,其中每个ID有前2条记录,如下所示:
id value
0 1 1
1 1 2
3 2 1
4 2 2
7 3 1
8 4 1
我可以在groupby
之后对组内的记录进行编号:
dfN = df.groupby('id').apply(lambda x:x['value'].reset_index()).reset_index()
它看起来像:
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
但是有没有更有效/更优雅的方法来实现这一点?还有没有更优雅的方法来对每个组中的记录进行编号(如SQL窗口函数row_number())。
6条答案
按热度按时间2exbekwf1#
你有没有试
生成的输出:
(Keep请记住,根据您的数据,您可能需要在此之前进行排序/排序)
编辑:正如提问者提到的,使用
删除多索引并拼合结果:
stszievb2#
Since 0.14.1,您现在可以在
groupby
对象上执行nlargest
和nsmallest
操作:有一点奇怪的是,你也得到了原始索引,但是这可能真的很有用,取决于你的原始索引是什么。
如果您对它不感兴趣,可以执行
.reset_index(level=1, drop=True)
来完全摆脱它。(Note:From 0.17.1您也可以在DataFrameGroupBy上执行此操作,但目前它仅适用于
Series
和SeriesGroupBy
。)cmssoen23#
有时候提前对整个数据进行排序是非常耗时的,我们可以先进行groupby,然后对每个组进行topk:
oug3syen4#
lzfw57am5#
这适用于重复值
如果前n个值中存在重复值,并且只需要唯一值,则可以执行以下操作:
x6yk4ghg6#
要获取每个组的前N行,另一种方法是通过
groupby().nth[:N]
。此调用的结果与groupby().head(N)
相同。例如,对于每个ID的前2行,调用:为了获得每组的最大N值,我建议两种方法。
1.首先按“id”和“value”排序(通过适当使用
ascending
参数,确保“id”按升序排序,“value”按降序排序),然后调用groupby().nth[]
。1.另一种方法是对每个组的值进行排序,并使用这些排序进行过滤。
这两种方法都比
groupby().apply()
和groupby().nlargest()
调用快得多,正如这里的其他答案(1、2、3)所建议的那样。在一个具有100 k行和8000个组的样本上,%timeit
测试显示它比这些解决方案快24-150倍。此外,除了切片,您还可以将列表/元组/范围传递给
.nth()
调用: