NumPy中的加权标准差


76

numpy.average()有权重选项,但numpy.std()没有。有没有人建议解决方法?


顺便说一句,加权std dev的计算实际上是一个相当复杂的主题-有多种方法可以实现。请参阅此处进行详细讨论: stata.com/support/faqs/statistics/…–
JohnE

Answers:


128

接下来的简短“手动计算”如何?

def weighted_avg_and_std(values, weights):
    """
    Return the weighted average and standard deviation.

    values, weights -- Numpy ndarrays with the same shape.
    """
    average = numpy.average(values, weights=weights)
    # Fast and numerically precise:
    variance = numpy.average((values-average)**2, weights=weights)
    return (average, math.sqrt(variance))

6
为什么不numpy.average再次使用方差?
user2357112支持Monica

4
只是想指出,这将产生偏差方差。对于小样本量,您可能需要重新缩放方差(在sqrt之前)以获得无偏方差。参见en.wikipedia.org/wiki/…–
Corey

1
是的,无偏方差估算器会略有不同。由于问题要求的加权版本,因此该答案给出了标准偏差numpy.std()
Eric O Lebigot 2014年

1
thx这个解决方案...但是为什么要用math.sqrt而不是np.sqrt最后呢?
拉斐尔18'Oct

1
np.sqrt()会起作用,但是因为它variance是一个简单的(Numpy)浮点数(而不是NumPy数组),所以math.sqrt()它更加显式和适当(因此,如果这很重要,则通常更快)。
Eric O Lebigot

40

其中有一个类别,statsmodels可让您轻松计算加权统计信息:statsmodels.stats.weightstats.DescrStatsW

假设此数据集和权重:

import numpy as np
from statsmodels.stats.weightstats import DescrStatsW

array = np.array([1,2,1,2,1,2,1,3])
weights = np.ones_like(array)
weights[3] = 100

初始化类(请注意,此时您必须输入校正因子,即自由度增量):

weighted_stats = DescrStatsW(array, weights=weights, ddof=0)

然后您可以计算:

  • .mean加权平均值

    >>> weighted_stats.mean      
    1.97196261682243
    
  • .std所述加权的标准偏差

    >>> weighted_stats.std       
    0.21434289609681711
    
  • .var加权方差

    >>> weighted_stats.var       
    0.045942877107170932
    
  • .std_mean加权平均值的标准误差

    >>> weighted_stats.std_mean  
    0.020818822467555047
    

    万一您对标准误差和标准偏差之间的关系感兴趣,请执行以下操作:标准误差的ddof == 0计算公式为()为加权标准偏差除以权重总和的平方根减去1(版本对应的来源)statsmodelsGitHub上的0.9):

    standard_error = standard_deviation / sqrt(sum(weights) - 1)
    

要使用此方法轻松计算加权变异系数,请参见此答案
Acumenus

14

这里还有一个选择:

np.sqrt(np.cov(values, aweights=weights))

6

在numpy / scipy中似乎还没有这样的功能,但是有一张票证提出了这个附加功能。在那里,您将找到Statistics.py,它实现了加权标准差。


1

gaborous提出了一个很好的例子:

import pandas as pd
import numpy as np
# X is the dataset, as a Pandas' DataFrame
mean = mean = np.ma.average(X, axis=0, weights=weights) # Computing the 
weighted sample mean (fast, efficient and precise)

# Convert to a Pandas' Series (it's just aesthetic and more 
# ergonomic; no difference in computed values)
mean = pd.Series(mean, index=list(X.keys())) 
xm = X-mean # xm = X diff to mean
xm = xm.fillna(0) # fill NaN with 0 (because anyway a variance of 0 is 
just void, but at least it keeps the other covariance's values computed 
correctly))
sigma2 = 1./(w.sum()-1) * xm.mul(w, axis=0).T.dot(xm); # Compute the 
unbiased weighted sample covariance

加权无偏样本协方差的正确方程式,URL(版本:2016-06-28)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.