python - 将多个函数应用于多个 groupby 列

docs展示如何使用以输出列名作为键的 dict 一次在 groupby 对象上应用多个函数:

In [563]: grouped['D'].agg({'result1' : np.sum,
   .....:                   'result2' : np.mean})
   .....:
Out[563]: 
      result2   result1
A                      
bar -0.579846 -1.739537
foo -0.280588 -1.402938

但是,这仅适用于 Series groupby 对象。当一个 dict 类似地传递给一个 groupby DataFrame 时,它​​期望键是该函数将应用于的列名。

我想要做的是将多个函数应用于多个列(但某些列将被多次操作)。此外,某些函数将依赖于 groupby 对象中的其他列(如 sumif 函数)。我目前的解决方案是逐列进行,并执行类似于上面的代码的操作,将 lambdas 用于依赖于其他行的函数。但这需要很长时间,(我认为遍历 groupby 对象需要很长时间)。我必须对其进行更改,以便在一次运行中遍历整个 groupby 对象,但我想知道 pandas 中是否有内置方法可以稍微干净地做到这一点。

例如,我尝试过类似

grouped.agg({'C_sum' : lambda x: x['C'].sum(),
             'C_std': lambda x: x['C'].std(),
             'D_sum' : lambda x: x['D'].sum()},
             'D_sumifC3': lambda x: x['D'][x['C'] == 3].sum(), ...)

但正如预期的那样,我得到了一个 KeyError(因为如果从 DataFrame 调用 agg,则键必须是一列)。

是否有任何内置方法可以做我想做的事情,或者有可能添加此功能,还是我只需要手动遍历 groupby?

最佳答案

当前接受的答案的后半部分已过时并且有两个弃用。首先也是最重要的,您不能再将字典字典传递给 agg groupby 方法。其次,永远不要使用.ix

如果您希望同时处理两个单独的列,我建议使用 apply 方法,该方法隐式地将 DataFrame 传递给应用函数。让我们使用与上面类似的数据框

df = pd.DataFrame(np.random.rand(4,4), columns=list('abcd'))
df['group'] = [0, 0, 1, 1]
df

          a         b         c         d  group
0  0.418500  0.030955  0.874869  0.145641      0
1  0.446069  0.901153  0.095052  0.487040      0
2  0.843026  0.936169  0.926090  0.041722      1
3  0.635846  0.439175  0.828787  0.714123      1

从列名映射到聚合函数的字典仍然是执行聚合的绝佳方式。

df.groupby('group').agg({'a':['sum', 'max'], 
                         'b':'mean', 
                         'c':'sum', 
                         'd': lambda x: x.max() - x.min()})

              a                   b         c         d
            sum       max      mean       sum  <lambda>
group                                                  
0      0.864569  0.446069  0.466054  0.969921  0.341399
1      1.478872  0.843026  0.687672  1.754877  0.672401

如果你不喜欢那个丑陋的 lambda 列名,你可以使用普通函数并为特殊的 __name__ 属性提供自定义名称,如下所示:

def max_min(x):
    return x.max() - x.min()

max_min.__name__ = 'Max minus Min'

df.groupby('group').agg({'a':['sum', 'max'], 
                         'b':'mean', 
                         'c':'sum', 
                         'd': max_min})

              a                   b         c             d
            sum       max      mean       sum Max minus Min
group                                                      
0      0.864569  0.446069  0.466054  0.969921      0.341399
1      1.478872  0.843026  0.687672  1.754877      0.672401

使用 apply 并返回一个系列

现在,如果您有多个列需要一起交互,那么您就不能使用 agg,它会隐式地将 Series 传递给聚合函数。当使用 apply 时,整个组作为 DataFrame 被传递到函数中。

我建议创建一个返回所有聚合系列的自定义函数。使用 Series 索引作为新列的标签:

def f(x):
    d = {}
    d['a_sum'] = x['a'].sum()
    d['a_max'] = x['a'].max()
    d['b_mean'] = x['b'].mean()
    d['c_d_prodsum'] = (x['c'] * x['d']).sum()
    return pd.Series(d, index=['a_sum', 'a_max', 'b_mean', 'c_d_prodsum'])

df.groupby('group').apply(f)

         a_sum     a_max    b_mean  c_d_prodsum
group                                           
0      0.864569  0.446069  0.466054     0.173711
1      1.478872  0.843026  0.687672     0.630494

如果您喜欢 MultiIndexes,您仍然可以返回一个带有这样的系列:

    def f_mi(x):
        d = []
        d.append(x['a'].sum())
        d.append(x['a'].max())
        d.append(x['b'].mean())
        d.append((x['c'] * x['d']).sum())
        return pd.Series(d, index=[['a', 'a', 'b', 'c_d'], 
                                   ['sum', 'max', 'mean', 'prodsum']])

df.groupby('group').apply(f_mi)

              a                   b       c_d
            sum       max      mean   prodsum
group                                        
0      0.864569  0.446069  0.466054  0.173711
1      1.478872  0.843026  0.687672  0.630494

https://stackoverflow.com/questions/14529838/

相关文章:

python - 使用 Python 解析 HTML

python - 为 Python 项目添加 .gitignore 文件的最佳实践?

c - 为什么需要 .bss 段?

linux - 查找文件并将它们 tar(带空格)

linux - 查找连接到 Linux 机器的所有存储设备

python - 子进程 Popen 和 call 有什么区别(我该如何使用它们)?

linux - 如何在 Linux 上将行添加到文件末尾

python - 从字符串变量导入模块

linux - 在 shell 中获取文件大小(以字节为单位)的可移植方法

python - 为什么 Python 的 math.ceil() 和 math.floor() 操