【问题标题】:Must produce aggregated value. I swear that I am必须产生聚合价值。我发誓我是
【发布时间】:2019-05-07 01:41:13
【问题描述】:

考虑pd.Seriess

a = np.arange(4)
mux = pd.MultiIndex.from_product([list('ab'), list('xy')])
s = pd.Series([a] * 4, mux)
print(s)

a  x    [0, 1, 2, 3]
   y    [0, 1, 2, 3]
b  x    [0, 1, 2, 3]
   y    [0, 1, 2, 3]
dtype: object

问题
s 的每个元素都是一个 numpy.array。当我尝试在组内求和时,我得到一个错误,因为 groupby 函数期望结果是标量......(我猜)

s.groupby(level=0).sum()
Exception                                 Traceback (most recent call last)
<ipython-input-627-c5b3bf6890ea> in <module>()
----> 1 s.groupby(level=0).sum()

C:\Anaconda2\lib\site-packages\pandas\core\groupby.pyc in f(self)
    101             raise SpecificationError(str(e))
    102         except Exception:
--> 103             result = self.aggregate(lambda x: npfunc(x, axis=self.axis))
    104             if _convert:
    105                 result = result._convert(datetime=True)

C:\Anaconda2\lib\site-packages\pandas\core\groupby.pyc in aggregate(self, func_or_funcs, *args, **kwargs)
   2584                 return self._python_agg_general(func_or_funcs, *args, **kwargs)
   2585             except Exception:
-> 2586                 result = self._aggregate_named(func_or_funcs, *args, **kwargs)
   2587 
   2588             index = Index(sorted(result), name=self.grouper.names[0])

C:\Anaconda2\lib\site-packages\pandas\core\groupby.pyc in _aggregate_named(self, func, *args, **kwargs)
   2704             output = func(group, *args, **kwargs)
   2705             if isinstance(output, (Series, Index, np.ndarray)):
-> 2706                 raise Exception('Must produce aggregated value')
   2707             result[name] = self._try_cast(output, group)
   2708 

Exception: Must produce aggregated value

解决方法
当我使用applynp.sum 时,它工作正常。

s.groupby(level=0).apply(np.sum)

a    [0, 2, 4, 6]
b    [0, 2, 4, 6]
dtype: object

问题
有没有优雅的方法来处理这个?


真正的问题
我其实是想这样用agg

s.groupby(level=0).agg(['sum', 'prod'])

但它以同样的方式失败。
获得这个的唯一方法是

pd.concat([g.apply(np.sum), g.apply(np.prod)],
          axis=1, keys=['sum', 'prod'])

但这并不能很好地推广到更长的转换列表。

【问题讨论】:

  • 我认为你的工作非常优雅!
  • @StevenG 抱歉,我之前删除了这个问题,因为它的格式不正确。我不得不跑,现在我正试图加强这个问题。我真正的问题是,如果不使用我的解决方法和pd.concat,我无法聚合
  • 我目前找不到好的链接,但是是的,不支持非标量元素。
  • 来自注释:Numpy 函数 mean/median/prod/sum/std/var 是特殊情况,因此默认行为是沿 axis=0 应用函数(例如,np.mean(arr_2d, axis =0)) 而不是模仿默认的 Numpy 行为(例如,np.mean(arr_2d))。 see this at the bottom

标签: python pandas


【解决方案1】:

from this well explained answer 您可以将您的 ndarray 转换为 list,因为 pandas 似乎正在检查输出是否为 ndarray,这就是您收到此错误的原因:

s.groupby(level=0).agg({"sum": lambda x: list(x.sum()), "prod":lambda x: list(x.prod())})

输出[249]:

            sum          prod
a  [0, 2, 4, 6]  [0, 1, 4, 9]
b  [0, 2, 4, 6]  [0, 1, 4, 9]

【讨论】:

    【解决方案2】:

    Pandas 并非旨在将数组作为值。将DataFrame 用于s 而不是Series 是更好的做法。这将为您提供预期的行为,并且比使用 lambdas/lists 快得多。

    您可以通过以下方式轻松转换为DataFrame

    s = s.apply(pd.Series)
    

    那时,在任何级别上进行聚合都非常容易。

    s.groupby(level=0).agg(['sum', 'prod'])
    
        0        1        2        3     
      sum prod sum prod sum prod sum prod
    a   0    0   2    1   4    4   6    9
    b   0    0   2    1   4    4   6    9
    

    您可以就此打住,但我认为这不是您理想中想要的格式。重新堆叠聚合很容易。

    test = s.groupby(level=0).agg(['sum', 'prod'])
    test = test.stack(level=0).unstack()
    test
    
      prod          sum         
         0  1  2  3   0  1  2  3
    a    0  1  4  9   0  2  4  6
    b    0  1  4  9   0  2  4  6
    

    此时您可以像您期望的那样调用每个产品并求和。

    test['prod']
    
       0  1  2  3
    a  0  1  4  9
    b  0  1  4  9
    

    或者如果你想把它作为一个数组返回:

    test['prod'].values
    
    array([[0, 1, 4, 9],
           [0, 1, 4, 9]])
    

    【讨论】:

      猜你喜欢
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-27
      • 2010-12-22
      • 1970-01-01
      • 2021-10-27
      • 2021-11-01
      • 2014-05-04
      相关资源
      最近更新 更多