Jak obliczyć wariancję podziału zmiennych

15

Prowadzę eksperyment, w którym równolegle zbieram (niezależne) próbki, obliczam wariancję każdej grupy próbek, a teraz chcę połączyć wszystkie, aby znaleźć całkowitą wariancję wszystkich próbek.

Trudno mi znaleźć na to pochodne, ponieważ nie jestem pewien terminologii. Myślę o tym jak o podziale jednego RV.

Więc chcę znaleźć Var(X) z Var(X1) , Var(X2) , ... i Var(Xn) , gdzie X = [X1,X2,,Xn] .

EDYCJA: Partycje nie mają tego samego rozmiaru / liczności, ale suma rozmiarów partycji jest równa liczbie próbek w ogólnym zestawie próbek.

EDYCJA 2: Istnieje wzór na obliczenia równoległe , ale obejmuje on tylko przypadek partycji na dwa zbiory, a nie n zbiorów.

galamina
źródło
Czy to to samo, co moje pytanie tutaj: mathoverflow.net/questions/64120/…
Co oznacza ten ostatni nawias? A co rozumiesz przez „całkowitą wariancję”? Czy jest to coś innego niż wariancja połączonego zestawu danych?
whuber
@ whuber, który ostatni nawias? „całkowita wariancja” oznacza wariancję całkowitego zestawu danych.
gallamine
Wyrażenie może znaczyć wiele rzeczy (choć konwencjonalnie byłby to wektor): szukałem wyjaśnienia. [X1,X2,,Xn]
whuber

Odpowiedzi:

22

Formuła jest dość prosta, jeśli wszystkie podpróbki mają ten sam rozmiar próby. Jeśli miał sub-próbek o rozmiarze K (w sumie g k próbek), a następnie odchylenie w połączonej próbki w zależności od średniej e j i wariancji V j każdego sub-próbce: V do R ( X 1 , , X g k ) = k - 1gkgkEjVjgdzie przezVar(Ej)oznacza wariancję średnich próbek.

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

Demonstracja w języku 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

Jeśli rozmiary próbek nie są równe, formuła nie jest taka ładna.

EDYCJA: wzór na nierówne wielkości próbek

Jeżeli istnieją sub-próbek, zaś każda z k j , j = 1 , ... , G elementy w sumie n = Ď k j wartości, wtedy V R ( X 1 , ... , x n ) = 1gkj,j=1,,gn=kj gdzie ˉ X =( g j = 1 kj ˉ X j)/njest średnią ważoną wszystkich średnich (i jest równa średniej wszystkich wartości).

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

Ponownie demonstracja:

> 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

Aniko
źródło
dzięki. Niestety nie mogę zagwarantować, że moje partycje są tego samego rozmiaru. Prowadzę masowo równoległy proces, w którym muszę obliczyć wariancje każdej partycji równolegle, a następnie połączyć na końcu, ale wyniki / próbki z każdego równoległego procesu nie są równe (jest to symulacja Monte Carlo otrzymanych fotonów).
galamina
3
Nie mogę dać +1, super pomocna formuła do obliczeń równoległych w środowisku hurtowni danych
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))
Mr Tsjolder
źródło