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

Posted

技术标签:

【中文标题】在 Pandas 中使用 group by 时如何将“first”和“last”函数应用于列?【英文标题】:How to apply "first" and "last" functions to columns while using group by in pandas? 【发布时间】:2013-02-06 17:11:57 【问题描述】:

我有一个数据框,我想按特定列(或者换句话说,按特定列中的值)对它进行分组。我可以通过以下方式做到这一点: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。所以,我的问题是:为什么会发生以及如何解决这个问题。

添加

Here我找到了下面的例子:

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

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

【问题讨论】:

您不需要np,它可以与普通的旧sum 一起使用(只是效率较低)。 numpy 是用 pandas 导入的(如果你 import pandas as pdpd.np),但为了方便,大多数人也会单独导入它。 【参考方案1】:
c_df = b_df.groupby('time').agg(first_x=('x', lambda x: list(x)[0]),
                                last_x=('x', lambda x: list(x)[-1]),
                                last_y=('y', lambda x: list(x)[-1]))

【讨论】:

【参考方案2】:

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

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

我希望这会有所帮助。

【讨论】:

【参考方案3】:

不要使用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')

【讨论】:

这是解决此问题的最新方法。 有没有办法将 kwarg 也传递给函数,例如numeric_only=True?【参考方案4】:

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

要使用 agg 在 DataFrame 上复制 groupby first 方法的行为,您可以使用 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

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

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

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 行...而 IIRC 对于 DataFrame groupbys 它在 0.13 之前被破坏...有一个 @987654340 nth 的 @ 选项。

您可以使用字符串而不是内置函数(尽管 IIRC pandas 发现它是 sum 内置函数并应用 np.sum):

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

【讨论】:

以防万一它对任何人有用,根据the docs,irow 现在已被弃用(x.iloc[0] 可以代替) @cd98 感谢您指出这一点,我已经用更新的语法更新了这个:) 我对@9​​87654325@ 感到困惑;它指出:Aggregating functions are ones that reduce the dimension of the returned objects, for example: mean, sum, size, count, std, var, sem, describe, first, last, nth, min, max. 那么他们在说什么? 在某种意义上这里有三种类型的映射:聚合、应用和过滤(上面是一种过滤器,虽然它使用了 agg 动词)。这很复杂,您可以使用 either agg 或 apply 来完成 .iloc[0] 工作,不知道我为什么使用 agg,apply 可能是一个更好的描述。由于这篇文章我修复了 nth 以更好地工作,所以 IMO 这是这里的首选解决方案。【参考方案5】:

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

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

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

或类似的东西..

【讨论】:

以上是关于在 Pandas 中使用 group by 时如何将“first”和“last”函数应用于列?的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 数据框中的 MultiIndex Group By

Python,在 Pandas DataFrame 的“group concat”中使用“order by”

pandas group by 在 Datetime 上,格式为 mm.dd.yyyy [重复]

group by用法

python Python Pandas中字符串的GROUP BY

Pandas 上的 SQL“GROUP BY HAVING”等价物是啥?