A variância pode ser expressa como proporcional à diferença ao quadrado entre cada valor e o valor médio, ou (como muitos threads aqui em stats.SE documentados, como esta resposta que escrevi para outra pergunta) ela pode ser expressa como proporcional ao quadrado diferença de pares entre cada amostra.
Então sabemos:
Var(x)=1n⋅∑i(Xi−X¯¯¯¯)2=12n2⋅∑i,j(Xi−Xj)2
Digamos que você adicione outra amostra, indexada como o último índice, . Sua variação anterior seria:k
Varold(x)=12(n−1)2⋅∑i<k,j<k(Xi−Xj)2
Sua nova variação é
Varnew(x)=12n2⋅∑i,j(Xi−Xj)2=12n2⋅(∑i<k,j<k(Xi−Xj)2+∑j<k(Xk−Xj)2+∑i<k(Xi−Xk)2)
Mas
∑j<k(Xk−Xj)2=∑i<k(Xi−Xk)2∑i<k,j<k(Xi−Xj)2=2(n−1)2⋅Varold(x)
assim
Varnew(x)=(n−1n)2Varold(x)+1n2∑j<k(Xk−Xj)2
Como o @ MarkL.Stone disse nos comentários, isso ainda não é eficiente, porque devemos manter todos os . Então, vamos expandir a fórmula para chegar a algo mais tratável.Xi
1n2∑j<k(Xk−Xj)2=1n2∑j<k(X2k−2⋅Xj⋅Xk+X2j)=1n2(∑j<kX2k−2⋅Xk⋅∑j<kXj+∑j<kX2j)=1n2(k⋅X2k−2⋅Xk⋅(k−1)⋅Xold¯¯¯¯¯¯¯¯¯+(k−1)⋅X2old¯¯¯¯¯¯¯¯¯)
Porque
∑j<kXj=(k−1)⋅Xold¯¯¯¯¯¯¯¯¯∑j<kX2j=(k−1)⋅X2old¯¯¯¯¯¯¯¯¯
O formulário final é então
Varnew(x)=(n−1n)2Varold(x)+1n2(k⋅X2k−2⋅Xk⋅(k−1)⋅Xold¯¯¯¯¯¯¯¯¯+(k−1)⋅X2old¯¯¯¯¯¯¯¯¯)
Você pode usar esta fórmula para atualizar a variação efetivamente em memória. Você também pode complementá-lo para usar lotes em vez de atualizações de ponto único.
Basicamente, você precisa armazenar a média, a média das amostras ao quadrado e a variação a cada iteração e usá-la para atualizar a fórmula de variação.
Mais longe
X2old¯¯¯¯¯¯¯¯¯=Varold(x)+(Xold¯¯¯¯¯¯¯¯¯)2∴Varnew(x)=(n−1n)2Varold(x)+1n2(k⋅X2k−2⋅Xk⋅(k−1)⋅Xold¯¯¯¯¯¯¯¯¯+(k−1)⋅(Varold(x)+(Xold¯¯¯¯¯¯¯¯¯)2))
O que reduz o número de quantidades que precisam ser armazenadas para 2.