4

我不确定这是否是我做错或不理解的事情,或者它是否可能是 pandas 交叉表或 numpy 大小函数中的错误。

我在这里使用熊猫示例中的简单数据框

>>> df = DataFrame({'A': ['one', 'one', 'two', 'three'] * 6, 'B': ['A', 'B', 'C'] * 8, 'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 4, 'D': np.random.randn(24), 'E': np.random.randn(24)})

使用 margins=True 做一个简单的交叉表以获得总计按预期工作:

>>> crosstab(rows=[df['A'],df['B']], cols=[df['C']], margins=True)
C        bar  foo  All
A     B               
one   A    2    2    4
      B    2    2    4
      C    2    2    4
three A    2    0    2
      B    0    2    2
      C    2    0    2
two   A    0    2    2
      B    2    0    2
      C    0    2    2
All       12   12   24

直接使用 np.size 函数给出相同的结果:

>>> crosstab(rows=[df['A'],df['B']], cols=[df['C']], margins=True, aggfunc=[np.size])
C        bar  foo  All
A     B               
one   A    2    2    4
      B    2    2    4
      C    2    2    4
three A    2    0    2
      B    0    2    2
      C    2    0    2
two   A    0    2    2
      B    2    0    2
      C    0    2    2
All       12   12   24

Pandas 允许您传入多个聚合函数以在一个交叉表中获取计数和平均值。但是,当我这样做时, foo 和 bar 的大小计数是上次调用中的两倍,但总体总数保持正确。

>>> crosstab(rows=[df['A'],df['B']], cols=[df['C']], margins=True, aggfunc=[np.size, np.mean], values=df['D'])
         size                mean                    
C         bar  foo  All       bar       foo       All
A     B                                              
one   A     2    2    4  0.245998  0.076366  0.161182
      B     2    2    4 -0.739757  0.137780 -0.300988
      C     2    2    4 -1.555759 -1.446554 -1.501157
three A     2  NaN    2  1.216109       NaN  1.216109
      B   NaN    2    2       NaN  0.255482  0.255482
      C     2  NaN    2  0.732448       NaN  0.732448
two   A   NaN    2    2       NaN -0.273747 -0.273747
      B     2  NaN    2 -0.001649       NaN -0.001649
      C   NaN    2    2       NaN  0.685422  0.685422
All        24   24   24 -0.017102 -0.094208 -0.055655

我在这里错过了什么吗?为什么这在两种情况下表现不同?

4

1 回答 1

2

好的,我知道它在做什么。

翻遍了源代码pandas/pandas/tools/pivot.py,就到了语句

row_margin = data[cols + values].groupby(cols).agg(aggfunc)

这里 cols 是 df['C'],值是 df['D']。我们将这两件事按 cols 分组,然后应用聚合函数,在本例中为 np.size。每行看起来像

In [158]: data[cols + values].groupby(cols).nth(0)
Out[158]: 
     __dummy__
C             
bar  -1.823026
foo   0.465117

当我们调用np.size()它时,我们当然会得到 2。将所有这些 2 相加得到边距,我们最终得到 24,如果您只想要D'的计数,您可能会预期的两倍

也许其他人可以告诉我们这是否是预期的。我仍然对源代码的一部分感到困惑。如果我发现更多内容,我会进行编辑。

于 2013-06-22T17:12:56.503 回答