【问题标题】:Inconsistency in results of aggregating pandas groupby object using numpy.median vs other functions使用 numpy.median 与其他函数聚合 pandas groupby 对象的结果不一致
【发布时间】:2012-09-21 00:34:20
【问题描述】:

使用DataFrame(pandas作为pd,numpy作为np):

test = pd.DataFrame({'A' : [10,11,12,13,15,25,43,70],  
                     'B' : [1,2,3,4,5,6,7,8],  
                     'C' : [1,1,1,1,2,2,2,2]})


In [39]: test
Out[39]: 
    A  B  C
0  10  1  1
1  11  2  1
2  12  3  1
3  13  4  1
4  15  5  2
5  25  6  2
6  43  7  2
7  70  8  2

按“C”对 DF 进行分组并使用 np.mean(也包括 sum、min、max)进行聚合会在组内产生按列聚合:

In [40]: test_g = test.groupby('C')

In [41]: test_g.aggregate(np.mean)
Out[41]: 
       A    B
C            
1  11.50  2.5
2  38.25  6.5

但是,看起来使用 np.median 进行聚合会在组内产生 DataFrame-wise 聚合:

In [42]: test_g.aggregate(np.median)
Out[42]: 
      A     B
C            
1   7.0   7.0
2  11.5  11.5

(虽然使用groupby.median 方法似乎会产生预期的列式结果)

希望能解决以下问题:

  1. 这种结果的原因/机制是什么?
  2. 如果此行为得到确认,它将如何影响聚合分组的推荐“最佳实践”?其他聚合函数可以这样工作吗?

【问题讨论】:

    标签: python numpy aggregate pandas


    【解决方案1】:

    原因很有趣。可能一些 pandas 专家会想插话,但这归结为 numpy 和 pandas 之间的乒乓球。请注意,文档说:

    用于聚合组的函数。如果是一个函数,必须要么 在传递 DataFrame 或传递给 DataFrame.apply 时工作。如果 传一个dict,key必须是DataFrame列名

    第一件事是 2D (array_like),第二个方法归结为 1D array_likes 被传递给您提供的函数。

    这意味着聚合首先传入 2D 系列。在第一种情况下 (np.mean),numpy 知道数组有一个 .mean 属性,所以它会做它一直做的事情。但是它用axis=None 调用它(numpy 的默认值)。这使得 Pandas 抛出一个异常(它希望轴为 0 或 1,并且从不为 None),然后进入第二步,将其作为 1D 传递并且是万无一失的。

    但是,当您输入 np.median 时,numpy 数组没有 .median 属性,因此它会执行正常的 numpy 机制,即展平数组(即通常为 axis=None)。

    解决方法是使用test_g.aggregate([np.median, np.median]) 强制它始终采用第二条路径。或者什么也可以:test_g.aggregate(np.median, axis=0)axis=0 传递给np.median,从而告诉numpy 如何正确处理它。一般来说,我想知道 pandas 是否至少不应该发出警告,毕竟将结果广播到两列应该几乎不是想要的。

    【讨论】:

    • 谢谢,我怀疑问题出在pandas - numpy 接口和numpy 的数组处理,检查了aggregate docstring,但无法得出你所做的结论;)
    【解决方案2】:

    作为一种变通方法,请注意,pandas 有常用操作的快捷方法:

    In [12]: test.groupby('C').mean()
    Out[12]: 
           A    B
    C            
    1  11.50  2.5
    2  38.25  6.5
    
    In [13]: test.groupby('C').median()
    Out[13]: 
          A    B
    C           
    1  11.5  2.5
    2  34.0  6.5
    

    对于 sum、mean、median、max、min、first、last、std 之类的东西,您可以直接调用该方法,而不必担心 apply-to-DataFrame-but-failover-to-each-column GroupBy 引擎中的机制。

    【讨论】:

      【解决方案3】:

      我怀疑这是一个错误...所以I added it here

      同时(如果您原谅双关语),您可以使用.agg 方法:

      test_g.agg([np.mean,np.median])
              A             B        
           mean  median  mean  median
       C                             
       1  11.50    11.5   2.5     2.5
       2  38.25    34.0   6.5     6.5
      

      【讨论】:

      • agg 只是aggregate 的简写,但是您强制它始终在单列上工作,这可以解决这个问题。
      • 事实上,.agg 似乎不起作用:In [6]: test_g.agg(np.median) Out[6]: A B C 1 7.0 7.0 2 11.5 11.5 而 .agg([x]) 起作用:In [7]: test_g.agg([np.median]) Out[7]: A B median median C 1 11.5 2.5 2 34.0 6.5 seberg 的回答说明我认为。
      • 抱歉,在注释中格式化代码存在令人尴尬的困难;)
      • agg([np.median]) :) 是的。我只是想制定一个链接以传递axis=0,这是正确的方法。
      【解决方案4】:

      从 v 0.12 开始引入 DataFrame.median :http://pandas.pydata.org/pandas-docs/dev/generated/pandas.DataFrame.median.html

      在 v 0.12 之前,我认为该方法不存在。相反,您可以使用 numpy.median

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        • 2023-01-12
        • 1970-01-01
        • 2019-05-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多