Python:Numpy标准差错误

30

这是一个简单的测试

import numpy as np
data = np.array([-1,0,1])
print data.std()

>> 0.816496580928

我不明白这个结果是如何生成的?显然:

( (1^0.5 + 1^0.5 + 0^0.5)/(3-1) )^0.5 = 1

在MATLAB中,std([-1,0,1]) = 1。你能帮我理解一下numpy.std()是如何工作的吗?


9
除以N-1可以得到样本方差,但NumPy计算的是总体方差。 - Fred Foo
11
我会尽力为您翻译: 因为人们往往不注意总体标准差和样本标准差之间的区别,直到结果不符合预期,所以我会给这篇文章点赞。选择其中一个,并知道为什么要使用它,既有助于防止这个问题的发生,也可以迫使您更有效地思考问题的本质。这一切都源于不愉快的经历。 - schodge
3个回答

27
这个问题的关键在于你需要除以N(3),而不是N-1(2)。正如Iarsmans所指出的,numpy会使用总体方差而不是样本方差。
因此,真正的答案是sqrt(2/3),它恰好是0.8164965... 如果您想故意使用不同于默认值0的自由度值,请使用关键字参数ddof和一个正值:
np.std(data, ddof=1)

... 但在这里这样做会重新引入您最初的问题,因为 numpy 将会除以 N - ddof


抱歉,2只是一个打字错误。我认为np.std()就是通用标准差。如果它是样本标准差,那么应该是N-1。是否有一个函数用于样本标准差? - MacSanhe
@MacSanhe 啊,那样的话你犯错也就更有道理了! - BlackVegetable
@MacSanhe 已编辑并详细说明以解决您的问题。 - BlackVegetable
这似乎是不正确的。Numpy文档表明默认情况下使用未校正的样本标准差,ddof=0。ddof=1将启用总体方差(使其对样本均值的偏差较小)。或者我错过了什么? - Johannes Schaub - litb
让我检查一下自从我写这个答案以来是否有所改变。 - BlackVegetable
啊,混淆在这里是附录,我展示了如何在需要时更改自由度。回到这个问题上来,我不确定它是否非常相关。无论如何,我会清理格式以突出显示问题是用户除以N-1而不是N。使用N然后使用ddof=1实际上会重新引入原始问题! - BlackVegetable

6

在建议函数/方法不正确之前,阅读其帮助页面是值得的。该方法确切地执行文档字符串所述的操作,即除以3,因为默认情况下ddof为零。:

In [3]: numpy.std?

String form: <function std at 0x104222398>
File:        /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/core/fromnumeric.py
Definition:  numpy.std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False)
Docstring:
Compute the standard deviation along the specified axis.

...

ddof : int, optional
    Means Delta Degrees of Freedom.  The divisor used in calculations
    is ``N - ddof``, where ``N`` represents the number of elements.
    By default `ddof` is zero.

2
从Matlab转到NumPy时,您可能希望同时保留两者的文档。它们相似但在一些小而重要的细节上有所不同。基本上,它们对标准偏差的计算方式不同。我强烈建议检查任何您使用的计算标准偏差的工具(无论是口袋计算器还是编程语言)的文档,因为默认值并没有(抱歉!)标准化。
NumPy STD: http://docs.scipy.org/doc/numpy/reference/generated/numpy.std.html Matlab STD: http://www.mathworks.com/help/matlab/ref/std.html Numpy文档中的std有点晦涩,我个人认为,特别是考虑到NumPy文档通常相当清晰易懂。如果你阅读得足够深入:平均平方偏差通常被计算为x.sum() / N,其中N = len(x)。然而,如果指定了ddof,则使用除数N - ddof。在标准统计实践中,ddof=1提供了无偏的无限总体方差估计。(换言之,默认为总体标准差,设置ddof=1则为样本标准差)。
另一方面,Matlab文档明确解释了让你困惑的区别:数据向量X的标准差s有两个常见的教科书定义。[公式省略] n是样本中元素的数量。这两种形式的方程只在分母中n-1与n不同。 因此,默认情况下,Matlab计算样本标准差(分母中为N-1,因此更大以补偿这是一个样本),而Numpy计算总体标准差(分母中为N)。您可以使用ddof参数切换到样本标准差,或者任何其他您想要的分母(超出我的统计知识范围)。
最后,这并不能解决这个问题,但你可能会在某些时候发现这很有帮助。链接

出于好奇,我何时需要使用 ddof 的值,使得 ddof ∉ {0, 1} - PythonNut
1
我不知道,我只用过这两个。也许可以去 http://stats.stackexchange.com/ 上问问。 - schodge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接