Python pandas: 在groupby中选择第二小的值

6

我有一个如下所示的示例DataFrame:

import pandas as pd
import numpy as np
df = pd.DataFrame({'ID':[1,2,2,2,3,3,], 'date':array(['2000-01-01','2002-01-01','2010-01-01','2003-01-01','2004-01-01','2008-01-01'],dtype='datetime64[D]')})

我正在尝试获取每个ID组中第二早的日期。因此,我编写了以下函数:

def f(x):
    if len(x)==1:
        return x[0]
    else:
        x.sort()
        return x[1]

然后我写道:

df.groupby('ID').date.apply(lambda x:f(x))

结果出现了错误。

你能想办法使它正常工作吗?


2
使用nsmallest,它在0.14.1中添加:https://github.com/pydata/pandas/pull/7356 - Jeff
3个回答

7
这需要0.14.1版本。如果您有大的组(因为这不需要完全排序),它将非常高效。
In [32]: df.groupby('ID')['date'].nsmallest(2)
Out[32]: 
ID   
1   0   2000-01-01
2   1   2002-01-01
    3   2003-01-01
3   4   2004-01-01
    5   2008-01-01
dtype: datetime64[ns]

In [33]: df.groupby('ID')['date'].nsmallest(2).groupby(level='ID').last()
Out[33]: 
ID
1    2000-01-01
2    2003-01-01
3    2008-01-01
dtype: datetime64[ns]

你可以传递一个列表。 - Jeff
如果存在其他列,我该如何在数据框中保留它们? - lmiguelvargasf

3

请查看索引docs - 一般情况下,pandas默认按标签进行索引,而不是位置 - 这就是为什么会出现KeyError的原因。

在您的特定情况下,您可以使用基于位置的索引.iloc

In [266]: def f(x):
     ...:     if len(x)==1:
     ...:         return x.iloc[0]
     ...:     else:
     ...:         x.sort()
     ...:         return x.iloc[1]
     ...:     

In [267]: df.groupby('ID').date.apply(f)
Out[267]: 
ID
1    2000-01-01
2    2003-01-01
3    2008-01-01
Name: date, dtype: datetime64[ns]

有关.iloc.loc的特定文档部分请参见此处 - jmduke

1

在接受的答案中,您可能不希望将第一个和唯一的值作为第二个值返回(即,2000-01-01 不是第二个值,而是唯一的值)。如果是这种情况,您可以对每个组进行排名,并能够更通用地选择第一、第二、第三等最小值:

df['rank'] = df.sort_values('date').groupby('ID').cumcount()+1

对于第二小的值:
df[df['rank'] == 2]

this returns

ID  date        rank
2   2003-01-01  2
3   2008-01-01  2

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