Cómo calcular la varianza de una partición de variables

15

Estoy ejecutando un experimento en el que estoy reuniendo muestras (independientes) en paralelo, calculo la varianza de cada grupo de muestras y ahora quiero combinar todo para encontrar la varianza total de todas las muestras.

Me está costando encontrar una derivación para esto, ya que no estoy seguro de la terminología. Pienso en ello como una partición de un RV.

Entonces, quiero encontrar de V a r ( X 1 ) , V a r ( X 2 ) , ... y V a r ( X n ) , donde X = [ X 1 , X 2 , ... , X n ] .Var(X)Var(X1)Var(X2)Var(Xn)X[X1,X2,,Xn]

EDITAR: Las particiones no son del mismo tamaño / cardinalidad, pero la suma de los tamaños de partición es igual al número de muestras en el conjunto de muestras general.

EDIT 2: aquí hay una fórmula para un cálculo paralelo , pero solo cubre el caso de una partición en dos conjuntos, no n conjuntos.

gallamina
fuente
¿Es esto lo mismo que mi pregunta aquí: mathoverflow.net/questions/64120/…
¿Qué significa ese último paréntesis? ¿Y qué quieres decir con "varianza total"? ¿Es algo más que la varianza del conjunto de datos combinado?
Whuber
@whuber que último soporte? "varianza total" significa la varianza del conjunto de datos total.
gallamina
La expresión podría significar muchas cosas (aunque convencionalmente sería un vector): estaba buscando una aclaración. [X1,X2,,Xn]
Whuber

Respuestas:

22

La fórmula es bastante sencilla si todas las submuestras tienen el mismo tamaño de muestra. Si tenía submuestras de tamaño k (para un total de g k muestras), entonces la varianza de la muestra combinada depende de la media E j y la varianza V j de cada submuestra: V a r ( X 1 , , X g k ) = k - 1gkgkEjVjdonde porVar(Ej)significa la varianza de las medias muestrales.

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

Una demostración en 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

Si los tamaños de muestra no son iguales, la fórmula no es tan buena.

EDITAR: fórmula para tamaños de muestra desiguales

Si hay submuestras, cada una con k j , j = 1 , ... , g elementos para un total de n = k j valores, entonces V a r ( X 1 , ... , X n ) = 1gkj,j=1,,gn=kj donde ˉ X =( g j =

Var(X1,,Xn)=1n1(j=1g(kj1)Vj+j=1gkj(X¯jX¯)2),
X¯=(j=1gkjX¯j)/n es el promedio ponderado de todas las medias (y es igual a la media de todos los valores).

De nuevo, una demostració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

Aniko
fuente
Gracias. Desafortunadamente, no puedo garantizar que mis particiones sean del mismo tamaño. Estoy ejecutando un proceso masivamente paralelo donde necesito calcular las variaciones de cada partición en paralelo y luego combinarlas al final, pero los resultados / muestras de cada proceso paralelo no son iguales (es una simulación de Monte Carlo de fotones recibidos).
gallamina
3
No puedo hacer +1 en esta fórmula súper útil para el cálculo paralelo en un entorno de almacén de datos
Noah Yetter
1

Esto es simplemente un complemento a la respuesta de aniko con un bosquejo aproximado de la derivación y un código de python, por lo que todos los créditos van a aniko.

derivación

XjX={X1,X2,...,Xsol} ser uno de sol partes de los datos donde el número de elementos en cada parte es kj=El |XjEl |. Definimos la media y la varianza de cada parte para ser

mij=mi[Xj]=1kjyo=1kjXjyoVj=Vunr[Xj]=1kj-1yo=1kj(Xjyo-mij)2
respectivamente. Si establecemosnorte=j=1solkj, la varianza del conjunto de datos total viene dada por:
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
fuente