6

使用 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. 如果此行为得到确认,它将如何影响聚合分组的推荐“最佳实践”?其他聚合函数可以这样工作吗?
4

4 回答 4

5

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

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

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

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

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

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

于 2012-09-29T11:44:59.370 回答
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 之类的东西,您可以直接调用该方法,而不必担心应用到 DataFrame-but-failover-to-each-column 机制GroupBy 引擎。

于 2012-09-30T00:42:15.470 回答
1

我怀疑这是一个错误......所以我在这里添加了它

同时(如果你原谅双关语),你可以使用.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
于 2012-09-29T11:41:02.917 回答
0

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

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

于 2013-04-30T00:27:22.337 回答