熊猫无法通过聚合功能列表进行聚合

时间:2019-02-26 17:04:13

标签: python pandas aggregate

如何指定自定义聚合函数,以便在pandas.DataFrame.aggregate的列表参数中使用时正确运行?

给出熊猫的两列数据框...

import pandas as pd
import numpy as np
df = pd.DataFrame(index=range(10))
df['a'] = [ 3 * x for x in range(10) ]
df['b'] = [ 1 -2 * x for x in range(10) ]

...通过聚合函数规范列表进行聚合不是问题:

def ok_mean(x):
  return x.mean()

df.aggregate(['mean', np.max, ok_mean])
               a    b
mean        13.5    -8.0
amax        27.0    1.0
ok_mean     13.5    -8.0

但是当将聚合指定为(lambda或命名的)函数时,此操作将无法聚合:

def nok_mean(x):
  return np.mean(x)

df.aggregate([lambda x:  np.mean(x), nok_mean])
                   a                 b
   <lambda> nok_mean <lambda> nok_mean
0   0.0      0.0     1.0     1.0
1   3.0      3.0    -1.0    -1.0
2   6.0      6.0    -3.0    -3.0
3   9.0      9.0    -5.0    -5.0
4   12.0    12.0    -7.0    -7.0
...

混合汇总和非汇总规格会导致错误:

df.aggregate(['mean', nok_mean])
~/anaconda3/envs/tsa37_jup/lib/python3.7/site-packages/pandas/core/base.py in _aggregate_multiple_funcs(self, arg, _level, _axis)
    607         # if we are empty
    608         if not len(results):
--> 609             raise ValueError("no results")
    610 

虽然直接使用聚合功能(不在列表中)会产生预期的结果:

df.aggregate(nok_mean)
a    13.5
b    -8.0
dtype: float64

这是一个错误还是我在定义聚合函数时缺少某些东西?在我的真实项目中,我使用的是更复杂的聚合函数(例如this percentile one)。所以我的问题是:

  

如何解决此错误,如何指定自定义聚合功能?

请注意,在滚动,扩展或分组窗口上使用自定义聚合功能会得到预期的结果:

df.expanding().aggregate(['mean', nok_mean])
## returns cumulative aggregation results as expected

熊猫版本:0.23.4

2 个答案:

答案 0 :(得分:1)

我发现,使用非系列参数调用聚合函数时会失败:

def ok_mean(x):
  return np.mean(x.values)

def ok_mean2(x):
  if not isinstance(x,pd.Series):
    raise ValueError('need Series argument')
  return np.mean(x)

df.aggregate(['mean', ok_mean, ok_mean2])

似乎在这种情况下(在pandas.DataFrame.aggregate的列表参数中),pandas首先尝试将聚合函数应用于每个数据点,并且从失败的那一刻起,便退回到正确的行为(以要汇总的系列)。

使用装饰器强制执行Series参数:

def assert_argtype(clazz):
    def wrapping(f):
        def wrapper(s):
            if not isinstance(s,clazz):
                raise ValueError('needs %s argument' % clazz)
            return f(s)
        return wrapper
    return wrapping

@assert_argtype(pd.Series)
def nok_mean(x):
    return np.mean(x)

df.aggregate([nok_mean])
## OK now, decorator fixed it!

答案 1 :(得分:0)

基于对这个问题的回答Pandas - DataFrame aggregate behaving oddly

这看起来像是因为您是直接针对单个值而不是整个数据框中的整个系列调用np.mean。将功能更改为

def nok_mean(x):
    return x.mean()

现在,您可以应用多种功能:

df.agg(['mean', nok_mean])

返回

             a    b
mean      13.5 -8.0
nok_mean  13.5 -8.0