100

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

4

6 回答 6

159

下面简短的“手动计算”怎么样?

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))
于 2010-03-10T08:07:16.750 回答
44

有一个类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

你初始化类(注意你必须传入校正因子,此时的 delta自由度):

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 的平方根(版本的相应来源statsmodels0.9 在 GitHub 上):

    standard_error = standard_deviation / sqrt(sum(weights) - 1)
    
于 2016-04-07T00:57:27.370 回答
27

这是另一种选择:

np.sqrt(np.cov(values, aweights=weights))
于 2018-10-04T21:15:38.807 回答
6

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

于 2010-03-10T00:06:51.530 回答
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)

于 2017-11-09T16:20:41.277 回答
0

“频率权重”意义上的“样本”或“无偏”标准偏差的后续行动,因为“加权样本标准偏差 python”谷歌搜索导致这篇文章:

def frequency_sample_std_dev(X, n):
    """
    Sample standard deviation for X and n,
    where X[i] is the quantity each person in group i has,
    and n[i] is the number of people in group i.
    See Equation 6.4 of:
    Montgomery, Douglas, C. and George C. Runger. Applied Statistics 
     and Probability for Engineers, Enhanced eText. Available from: 
      WileyPLUS, (7th Edition). Wiley Global Education US, 2018.
    """
    n_groups = len(n)
    n_people = sum(n)
    lhs_numerator = sum([ni*Xi**2 for Xi, ni in zip(X, n)])
    rhs_numerator = sum([Xi*ni for Xi, ni in zip(X,n)])**2/n_people
    denominator = n_people-1
    var = (lhs_numerator - rhs_numerator) / denominator
    std = sqrt(var)
    return std

或通过@Eric 修改答案如下:

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

    values, weights -- Numpy ndarrays with the same shape.
    
    Assumes that weights contains only integers (e.g. how many samples in each group).
    
    See also https://en.wikipedia.org/wiki/Weighted_arithmetic_mean#Frequency_weights
    """
    average = np.average(values, weights=weights)
    variance = np.average((values-average)**2, weights=weights)
    variance = variance*sum(weights)/(sum(weights)-1)
    return (average, sqrt(variance))

print(weighted_sample_avg_std(X, n))
于 2021-09-18T00:33:19.607 回答