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

Rom*_*man 35 python group-by pandas

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

添加

在这里,我找到了以下示例:

grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean})
Run Code Online (Sandbox Code Playgroud)

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

And*_*den 33

我认为问题在于有两种不同的first方法共享名称但行为不同,一种用于groupby对象,另一种用于Series/DataFrame(用于时间序列).

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

grouped.agg(lambda x: x.iloc[0])
Run Code Online (Sandbox Code Playgroud)

例如:

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
Run Code Online (Sandbox Code Playgroud)

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

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

g.agg({1: lambda x: x.iloc[0]})
Run Code Online (Sandbox Code Playgroud)

在旧版本的熊猫中你可以使用irow方法(例如x.irow(0),参见之前的编辑.


几个更新的说明:

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

g.nth(0)  # first
g.nth(-1)  # last
Run Code Online (Sandbox Code Playgroud)

你必须要小心一点,作为默认行为firstlast忽略NaN行......和IIRC对于DataFrame groupbys它在0.13之前被破坏了...有一个dropna选项nth.

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

grouped['D'].agg({'result1' : "sum", 'result2' : "mean"})
Run Code Online (Sandbox Code Playgroud)

  • 我对[文档](http://pandas.pydata.org/pandas-docs/stable/groupby.html#aggregation)感到困惑;它指出:“聚合函数是减少返回对象维度的函数,例如:mean、sum、size、count、std、var、sem、describe、first、last、nth、min、max。”他们在谈论什么? (2认同)

小智 14

而不是使用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'})
Run Code Online (Sandbox Code Playgroud)