如何计算变量分区的方差


15

我正在运行一个实验,在该实验中我将并行收集(独立)样本,我计算了每组样本的方差,现在我想将所有样本合并起来以找到所有样本的总方差。

由于不确定术语,我很难找到这个的派生词。我认为它是一个RV的分区。

所以,我想找到V一种[RXVarX1个V一种[RX2,...,和V一种[RXñ,其中X = [X1个X2Xñ]

编辑:分区不是相同的大小/基数,但是分区大小的总和等于整个样本集中的样本数。

编辑2:这里有一个用于并行计算的公式,但是它仅涉及将分区分为两组而不是ñ组的情况。


这是一样的在这里我的问题:mathoverflow.net/questions/64120/...

最后一个括号是什么意思?“总差异”是什么意思?除了合并数据集的方差以外,还有其他什么吗?
ub

@whuber最后一个括号?“总方差”是指总数据集的方差。
加拉明2011年

表达式可能意味着很多事情(尽管通常是矢量):我正在寻找一个说明。[X1,X2,,Xn]
ub

Answers:


22

如果所有子样本都具有相同的样本量,则公式非常简单。如果您有个大小为k的子样本(总共g k个样本),则合并样本的方差取决于每个子样本的均值E j和方差V jV a r X 1X g k= k 1gkgkEjVj其中VarEj表示样本均值的方差。

Var(X1,,Xgk)=k1gk1(j=1gVj+k(g1)k1Var(Ej)),
Var(Ej)

R中的演示:

> x <- rnorm(100)
> g <- gl(10,10)
> mns <- tapply(x, g, mean)
> vs <- tapply(x, g, var)
> 9/99*(sum(vs) + 10*var(mns))
[1] 1.033749
> var(x)
[1] 1.033749

如果样本数量不相等,则公式不是很好。

编辑:不相等样本量的公式

如果存在个子样本,每个子样本具有k jj = 1 ... g个元素,总共n = k j个值,则 V a r X 1X n= 1gkj,j=1,,gn=kĴ

Var(X1,,Xn)=1n1(j=1g(kj1)Vj+j=1gkj(X¯jX¯)2),
X¯=(j=1gkjX¯j)/n

再次演示:

> k <- rpois(10, lambda=10)
> n <- sum(k)
> g <- factor(rep(1:10, k))
> x <- rnorm(n)
> mns <- tapply(x, g, mean)
> vs <- tapply(x, g, var)
> 1/(n-1)*(sum((k-1)*vs) + sum(k*(mns-weighted.mean(mns,k))^2))
[1] 1.108966
> var(x)
[1] 1.108966

(XjiX¯)2X¯j[(XjiX¯j)(X¯jX¯)]2, using the square of difference formula, and simplifying.


thanks. Unfortunately, I can't guarantee that my partitions are all the same size. I'm running a massively parallel process where I need to calculate the variances of each partition in parallel then combine in the end, but the results/samples from each parallel process are not equal (it's a Monte Carlo simulation of received photons).
gallamine

3
I can't +1 this enough, super helpful formula for parallel computation in a data warehouse environment
Noah Yetter

1

This is simply an add-on to the answer of aniko with a rough sketch of the derivation and some python code, so all credits go to aniko.

derivation

Let XjX={X1,X2,,Xg} be one of g parts of the data where the number of elements in each part is kj=|Xj|. We define the mean and the variance of each part to be

Ej=E[Xj]=1kji=1kjXjiVj=Var[Xj]=1kj1i=1kj(XjiEj)2
respectively. If we set n=j=1gkj, the variance of the total dataset is given by:
Var[X]=1n1j=1gi=1kj(XjiE[X])2=1n1j=1gi=1kj((XjiEj)(E[X]Ej))2=1n1j=1gi=1kj(XjiEj)22(XjiEj)(E[X]Ej)+(E[X]Ej)2=1n1j=1g(kj1)Vj+kj(E[X]Ej)2.
If we have the same size k for each part, i.e. j:kj=k, above formula simplifies to
Var[X]=1n1j=1g(k1)Vj+k(g1)Var[Ej]=k1n1j=1gVj+k(g1)k1Var[Ej]

python code

The following python function works for arrays that have been splitted along the first dimension and implements the "more complex" formula for differently sized parts.

import numpy as np

def combine(averages, variances, counts, size=None):
    """
    Combine averages and variances to one single average and variance.

    # Arguments
        averages: List of averages for each part.
        variances: List of variances for each part.
        counts: List of number of elements in each part.
        size: Total number of elements in all of the parts.
    # Returns
        average: Average over all parts.
        variance: Variance over all parts.
    """
    average = np.average(averages, weights=counts)

    # necessary for correct variance in case of multidimensional arrays
    if size is not None:
        counts = counts * size // np.sum(counts, dtype='int')

    squares = (counts - 1) * variances + counts * (averages - average)**2
    return average, np.sum(squares) / (size - 1)

It can be used as follows:

# sizes k_j and n
ks = np.random.poisson(10, 10)
n = np.sum(ks)

# create data
x = np.random.randn(n, 20)
parts = np.split(x, np.cumsum(ks[:-1]))

# compute statistics on parts
ms = [np.mean(p) for p in parts]
vs = [np.var(p, ddof=1) for p in parts]

# combine and compare
combined = combine(ms, vs, ks, x.size)
numpied = np.mean(x), np.var(x, ddof=1)
distance = np.abs(np.array(combined) - np.array(numpied))
print('combined --- mean:{: .9f} - var:{: .9f}'.format(*combined))
print('numpied  --- mean:{: .9f} - var:{: .9f}'.format(*numpied))
print('distance --- mean:{: .5e} - var:{: .5e}'.format(*distance))
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.