Cara menghitung varians dari partisi variabel

15

Saya menjalankan eksperimen di mana saya mengumpulkan sampel (independen) secara paralel, saya menghitung varian masing-masing kelompok sampel dan sekarang saya ingin menggabungkan semua untuk menemukan varian total dari semua sampel.

Saya mengalami kesulitan menemukan derivasi untuk ini karena saya tidak yakin dengan terminologi. Saya menganggapnya sebagai partisi dari satu RV.

Jadi saya ingin mencari Var(X) dari Var(X1) , Var(X2) , ..., dan Var(Xn) , di mana X = [X1,X2,,Xn] .

EDIT: Partisi tidak memiliki ukuran / kardinalitas yang sama, tetapi jumlah ukuran partisi sama dengan jumlah sampel dalam set sampel keseluruhan.

EDIT 2: Ada rumus untuk perhitungan paralel di sini , tetapi hanya mencakup kasus partisi menjadi dua set, bukan n set.

gallamine
sumber
Apakah ini sama dengan pertanyaan saya di sini: mathoverflow.net/questions/64120/…
Apa artinya braket terakhir itu? Dan apa yang Anda maksud dengan "varian total"? Apakah ini selain varian dari dataset gabungan?
whuber
@whuber braket yang terakhir? "total variance" berarti varian total dataset.
Gallamine
Ekspresi dapat berarti banyak hal (walaupun secara konvensional itu akan menjadi vektor): Saya mencari klarifikasi. [X1,X2,,Xn]
whuber

Jawaban:

22

Rumusnya cukup mudah jika semua sub-sampel memiliki ukuran sampel yang sama. Jika Anda memiliki -sampel sub ukuran k (untuk total sampel g k ), maka varians dari sampel gabungan tergantung pada rata-rata E j dan varians V j dari masing-masing sub-sampel: V a r ( X 1 , , X g k ) = k - 1gkgkEjVjmana olehVar(Ej)berarti varians dari mean sampel.

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

Demonstrasi dalam 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

Jika ukuran sampel tidak sama, rumusnya tidak begitu bagus.

EDIT: rumus untuk ukuran sampel yang tidak sama

gkj,j=1,,gn=kj

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

Sekali lagi, demonstrasi:

> 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
sumber
Terima kasih. Sayangnya, saya tidak dapat menjamin bahwa partisi saya semuanya berukuran sama. Saya sedang menjalankan proses paralel masif di mana saya perlu menghitung varian masing-masing partisi secara paralel kemudian menggabungkan pada akhirnya, tetapi hasil / sampel dari setiap proses paralel tidak sama (ini adalah simulasi Monte Carlo dari foton yang diterima).
Gallamine
3
Saya tidak bisa memberi +1 formula yang cukup dan sangat membantu ini untuk komputasi paralel di lingkungan data warehouse
Noah Yetter
1

Ini hanyalah add-on untuk jawaban aniko dengan sketsa kasar derivasi dan beberapa kode python, sehingga semua kredit masuk ke aniko.

penurunan

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

Ej=E[Xj]=1kji=1kjXjiVj=Var[Xj]=1kj1i=1kj(XjiEj)2
n=j=1gkj
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
sumber