【问题标题】:Pandas `agg` to list, "AttributeError / ValueError: Function does not reduce"Pandas `agg` 列出,“AttributeError / ValueError: Function does not reduce”
【发布时间】:2018-08-01 07:58:03
【问题描述】:

通常当我们使用 pandas 执行 groupby 操作时,我们可能希望跨多个系列应用多个函数。

groupby.agg 似乎是执行这些分组和计算的自然方式。

但是,groupby.agggroupby.apply 的实现方式似乎存在差异,因为我无法使用 agg 将其分组到列表中。元组和集合工作正常,这表明你只能通过agg 聚合到不可变类型。通过groupby.apply,我可以直接将一个系列汇总到一个列表中,没有任何问题。

下面是一个完整的例子。功能 (1)、(2)、(3) 成功完成。 (4) 返回# ValueError: Function does not reduce

import pandas as pd

df = pd.DataFrame([['Bob', '1/1/18', 'AType', 'blah', 'test', 'test2'],
                   ['Bob', '1/1/18', 'AType', 'blah2', 'test', 'test3'],
                   ['Bob', '1/1/18', 'BType', 'blah', 'test', 'test2']],
                  columns=['NAME', 'DATE', 'TYPE', 'VALUE A', 'VALUE B', 'VALUE C'])


def grouper(df, func):
    f = {'VALUE A': lambda x: func(x), 'VALUE B': 'last', 'VALUE C': 'last'}
    return df.groupby(['NAME', 'DATE', 'TYPE'])['VALUE A', 'VALUE B', 'VALUE C']\
             .agg(f).reset_index()

# (1) SUCCESS
grouper(df, set)

# (2) SUCCESS
grouper(df, tuple)

# (3) SUCCESS
df.groupby(['NAME', 'DATE', 'TYPE', 'VALUE B', 'VALUE C'])['VALUE A']\
  .apply(list).reset_index()

# (4) FAIL
grouper(df, list)

# AttributeError
# ValueError: Function does not reduce

【问题讨论】:

  • 这是存在的问题,您可以尝试 agg(list) 将返回相同的结果,使用 tuple 代替 list :-) 。石斑鱼(df,元组)
  • @Wen,澄清一下,这是 (a) 一个错误,(b) 尚未实施,(c) 有意处理吗?
  • 当pandas list 变得乱七八糟时,导致[1,2,3] 将被视为一个系列..
  • 我明白了,但您也可以将元组分配给系列,例如df['col'] = (1, 2, 3).

标签: python pandas group-by pandas-groupby


【解决方案1】:

经过大量调查,我发现这是一个错误,将在以后的 pandas 版本中修复。

0.22.x groupby.py中的违规代码,注意isinstance(res, list)

def _aggregate_series_pure_python(self, obj, func):

    group_index, _, ngroups = self.group_info

    counts = np.zeros(ngroups, dtype=int)
    result = None

    splitter = get_splitter(obj, group_index, ngroups, axis=self.axis)

    for label, group in splitter:
        res = func(group)
        if result is None:
            if (isinstance(res, (Series, Index, np.ndarray)) or
                    isinstance(res, list)):
                raise ValueError('Function does not reduce')
            result = np.empty(ngroups, dtype='O')

        counts[label] = group.shape[0]
        result[label] = res

    result = lib.maybe_convert_objects(result, try_float=0)
    return result, counts

Master branch of groupby.py, isinstance(res, list) 省略:

def _aggregate_series_pure_python(self, obj, func):

        group_index, _, ngroups = self.group_info

        counts = np.zeros(ngroups, dtype=int)
        result = None

        splitter = get_splitter(obj, group_index, ngroups, axis=self.axis)

        for label, group in splitter:
            res = func(group)
            if result is None:
                if (isinstance(res, (Series, Index, np.ndarray))):
                    raise ValueError('Function does not reduce')
                result = np.empty(ngroups, dtype='O')

            counts[label] = group.shape[0]
            result[label] = res

        result = lib.maybe_convert_objects(result, try_float=0)
        return result, counts

【讨论】:

    猜你喜欢
    • 2019-08-02
    • 2013-02-25
    • 2020-02-29
    • 2017-06-07
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    相关资源
    最近更新 更多