按熊猫数据框分组,然后在每组中选择最新的


78

如何对熊猫数据框的值进行分组并从每个组中选择最新(按日期)?

例如,给定一个按日期排序的数据框:

    id     product   date
0   220    6647     2014-09-01 
1   220    6647     2014-09-03 
2   220    6647     2014-10-16
3   826    3380     2014-11-11
4   826    3380     2014-12-09
5   826    3380     2015-05-19
6   901    4555     2014-09-01
7   901    4555     2014-10-05
8   901    4555     2014-11-01

按ID或产品分组,然后选择最早给出:

    id     product   date
2   220    6647     2014-10-16
5   826    3380     2015-05-19
8   901    4555     2014-11-01

Answers:


56

使用idxmaxgroupby,切片dfloc

df.loc[df.groupby('id').date.idxmax()]

    id  product       date
2  220     6647 2014-10-16
5  826     3380 2015-05-19
8  901     4555 2014-11-01

4
该解决方案对数百万条记录的处理速度非常慢
Hardik Gupta

90

您还可以tail与groupby一起使用以获取组的最后n个值:

df.sort_values('date').groupby('id').tail(1)

    id  product date
2   220 6647    2014-10-16
8   901 4555    2014-11-01
5   826 3380    2015-05-19

5
我喜欢它,因为它不仅可以应用于日期。
scottlittle

该选项比接受的答案要快得多,但可读性较差。还有一个假设可以groupby保留秩序,这不是问题吗?
Michael D


@ ade1e代码将如何更改以执行重新采样(例如每月或每年)并保持组的最后n个值,而不是求和/求平均值?
Andreuccio

15

我有一个类似的问题,最终使用drop_duplicates而不是groupby

与上面建议的其他方法相比,它在大型数据集上的运行速度显着提高。

df.sort_values(by="date").drop_duplicates(subset=["id"], keep="last")

    id  product        date
2  220     6647  2014-10-16
8  901     4555  2014-11-01
5  826     3380  2015-05-19

1
我通常也使用它,但是希望更快的解决方案是使用groupby。groupby直观上更有意义,通常是我们考虑解决此问题的方式!
rmilletich

11

给定一个按日期排序的数据框,您可以通过多种方式获得所需的内容:

像这样:

df.groupby(['id','product']).last()

像这样:

df.groupby(['id','product']).nth(-1)

或像这样:

df.groupby(['id','product']).max()

如果你不想idproduct显示为索引的使用groupby(['id', 'product'], as_index=False)。或者使用:

df.groupby(['id','product']).tail(1)

1

要使用.tail()为聚合方法,并让您的分组不变:

df.sort_values('date').groupby('id').apply(lambda x: x.tail(1))

        id  product date
id              
220 2   220 6647    2014-10-16
826 5   826 3380    2015-05-19
901 8   901 4555    2014-11-01
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.