Come calcolare la varianza di una partizione di variabili


15

Sto eseguendo un esperimento in cui sto raccogliendo campioni (indipendenti) in parallelo, calcolo la varianza di ciascun gruppo di campioni e ora voglio combinare tutti per trovare la varianza totale di tutti i campioni.

Sto facendo fatica a trovare una derivazione per questo in quanto non sono sicuro della terminologia. Lo considero una partizione di un camper.

Quindi voglio trovare da , , ... e , dove = .Var(X)Var(X1)Var(X2)Var(Xn)X[X1,X2,,Xn]

EDIT: le partizioni non hanno le stesse dimensioni / cardinalità, ma la somma delle dimensioni delle partizioni è uguale al numero di campioni nel set di campioni complessivo.

EDIT 2: esiste una formula per un calcolo parallelo qui , ma copre solo il caso di una partizione in due set, non in set.n


È la stessa della mia domanda qui: mathoverflow.net/questions/64120/…

Cosa significa quell'ultima parentesi? E cosa intendi per "varianza totale"? È qualcosa di diverso dalla varianza del set di dati combinato?
whuber

@whuber quale ultima parentesi? "varianza totale" indica la varianza del set di dati totale.
Gallamina

L'espressione [X1,X2,,Xn] potrebbe significare molte cose (anche se convenzionalmente sarebbe un vettore): stavo cercando un chiarimento.
whuber

Risposte:


22

La formula è abbastanza semplice se tutti i sottocampioni hanno le stesse dimensioni del campione. Se avevi sottocampioni di dimensione k (per un totale di g k campioni), la varianza del campione combinato dipende dalla media E j e dalla varianza V j di ciascun sottocampione: V a r ( X 1 , , X g k ) = k - 1gkgkEjVjdove perVar(Ej)indica la varianza delle medie campionarie.

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

Una dimostrazione in 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

Se le dimensioni del campione non sono uguali, la formula non è così bella.

EDIT: formula per campioni di dimensioni diverse

gkj,j=1,,gn=kj

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

Ancora una volta, una dimostrazione:

> 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


Grazie. Sfortunatamente, non posso garantire che le mie partizioni abbiano tutte le stesse dimensioni. Sto eseguendo un processo enormemente parallelo in cui ho bisogno di calcolare le varianze di ciascuna partizione in parallelo, quindi combinarle alla fine, ma i risultati / campioni di ciascun processo parallelo non sono uguali (è una simulazione Monte Carlo dei fotoni ricevuti).
Gallamina

3
Non riesco a fare +1 su questa formula abbastanza utile per il calcolo parallelo in un ambiente di data warehouse
Noah Yetter

1

Questo è semplicemente un componente aggiuntivo alla risposta di Aniko con uno schizzo approssimativo della derivazione e del codice Python, quindi tutti i crediti vanno ad Aniko.

derivazione

XjX={X1,X2,,Xg}gkj=|Xj|

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))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.