如何在pandas中使用group by时将“first”和“last”函数应用于列?

时间:2013-02-21 11:33:56

标签: python pandas group-by

我有一个数据框,我想按特定列(或者换句话说,来自特定列的值)对其进行分组。我可以通过以下方式完成:grouped = df.groupby(['ColumnName'])

我将此操作的结果想象为一个表,其中一些单元格可以包含值集而不是单个值。为了获得一个通常的表(即每个单元格只包含一个单个值的表),我需要指出我想用什么函数将单元格中的值集转换为单个值。

例如,我可以用它们的总和或它们的最小值或最大值来替换值集。我可以通过以下方式执行此操作:grouped.sum()grouped.min()等等。

现在我想为不同的列使用不同的函数。我发现我可以通过以下方式完成:grouped.agg({'ColumnName1':sum, 'ColumnName2':min})

但是,由于某些原因,我无法使用first。更详细地说,grouped.first()有效,但grouped.agg({'ColumnName1':first, 'ColumnName2':first})不起作用。结果我得到一个NameError:NameError: name 'first' is not defined。所以,我的问题是:为什么会这样,以及如何解决这个问题。

ADDED

Here我找到了以下示例:

grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean})

可能我还需要使用np?但在我的情况下,python不识别“np”。我应该导入吗?

4 个答案:

答案 0 :(得分:29)

我认为问题在于有两种不同的first方法共享一个名称但行为不同,一种用于groupby objectsanother for a Series/DataFrame(与时间序列有关)。

使用first复制groupby agg方法在DataFrame上的行为,您可以使用iloc[0](按索引获取每个组中的第一行(DataFrame / Series)) :

grouped.agg(lambda x: x.iloc[0])

例如:

In [1]: df = pd.DataFrame([[1, 2], [3, 4]])

In [2]: g = df.groupby(0)

In [3]: g.first()
Out[3]: 
   1
0   
1  2
3  4

In [4]: g.agg(lambda x: x.iloc[0])
Out[4]: 
   1
0   
1  2
3  4

类似地,您可以使用last复制iloc[-1]

注意:这将按列方式工作,等等:

g.agg({1: lambda x: x.iloc[0]})

在旧版本的pandas中,您可以使用irow方法(例如x.irow(0),请参阅之前的修改。


一些更新的说明:

使用nth groupby方法可以做得更好,速度更快> = 0.13:

g.nth(0)  # first
g.nth(-1)  # last

你必须要小心,因为firstlast的默认行为忽略了NaN行......而对于DataFrame groupbys来说它是IIRC,它在0.13之前被破坏了...... dropna有一个nth选项。

你可以使用字符串而不是内置插件(虽然IIRC pandas发现它是sum内置并应用np.sum):

grouped['D'].agg({'result1' : "sum", 'result2' : "mean"})

答案 1 :(得分:8)

不使用firstlast,而是使用agg方法中的字符串表示形式。例如关于OP的案例:

grouped = df.groupby(['ColumnName'])
grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean})

#you can do the string representation for first and last
grouped['D'].agg({'result1' : 'first', 'result2' : 'last'})

答案 2 :(得分:0)

我不确定这是否真的是问题,但summin是Python内置函数,它将一些迭代作为输入,而first是一种大熊猫方法系列对象,也许它不在您的命名空间中。此外,它需要其他东西作为输入(文档说一些偏移值)。

我想解决这个问题的一种方法是创建自己的first函数,并定义它以使Series对象作为输入,例如:

def first(Series, offset):
    return Series.first(offset)

或类似的......

答案 3 :(得分:0)

我将使用如下所示的自定义聚合器。

d = pd.DataFrame([[1,"man"], [1, "woman"], [1, "girl"], [2,"man"], [2, "woman"]],columns = 'number family'.split())
d

以下是输出:

    number family
 0       1    man
 1       1  woman
 2       1   girl
 3       2    man
 4       2  woman

现在,聚合将采用第一个元素和最后一个元素。

d.groupby(by = "number").agg(firstFamily= ('family', lambda x: list(x)[0]), lastFamily =('family', lambda x: list(x)[-1]))

此聚合的输出如下所示。

       firstFamily lastFamily
number                       
1              man       girl
2              man      woman

我希望这会有所帮助。