# Algoritmos para calcular la varianza

Los algoritmos para calcular la varianza juegan un papel importante en la estadística informática. Una dificultad clave en el diseño de buenos algoritmos para este problema es que las fórmulas de la varianza pueden incluir sumas de cuadrados, lo que puede llevar a problemas de inestabilidad numérica así como a rebosamiento cuando se trata de valores grandes.

## Algoritmo "ingenuo"

Una fórmula para calcular la varianza de una población completa de tamaño N es:
    $\sigma ^{2}={\overline {(x^{2})}}-{\bar {x}}^{2}=\displaystyle {\frac {\sum _{i=1}^{N}x_{i}^{2}-(\sum _{i=1}^{N}x_{i})^{2}/N}{N}}.\!$
Usando la corrección de Bessel para calcular una estimación no sesgada de la varianza poblacional de una muestra finita de observaciones n, la fórmula es:
    $s^{2}=\left({\frac {\sum _{i=1}^{n}x_{i}^{2}}{n}}-\left({\frac {\sum _{i=1}^{n}x_{i}}{n}}\right)^{2}\right)\cdot {\frac {n}{n-1}}.\!$
Por lo tanto, un algoritmo "ingenuo" para calcular la varianza estimada viene dado por el procedimiento:
* Let n ← 0, Sum ← 0, SumSq ← 0
* For each datum x:
** n ← n + 1
** Sum ← Sum + x
** SumSq ← SumSq + x × x
* Var = (SumSq − (Sum × Sum) / n) / (n − 1)
Este algoritmo se puede adaptar fácilmente para calcular la varianza de una población finita: simplemente, basta con dividr entre N en lugar de entre n - 1 en la última línea.
Como SumSq y (Sum×Sum)/n pueden ser números muy similares, cancelación de los restos puede llevar a que la precisión del resultado sea mucho menor que la precisión inherente de coma flotante utilizada para realizar el cálculo. Por lo tanto, se ha propuesto este algoritmo no debe utilizarse en la práctica. y varios algoritmos alternativos, numéricamente estables. Esto es particularmente malo si la desviación estándar es pequeña en relación con la media. Sin embargo, el algoritmo puede mejorarse adoptando el método de la media falsa.

### Cálculo de datos desplazados

Podemos usar una propiedad de la varianza para evitar la cancelación catastrófica en esta fórmula, a saber, la varianza es invariante con respecto a los cambios respecto a un parámetro de localización
    $\operatorname {Var} (X-K)=\operatorname {Var} (X).$
Siendo $K$ una constante cualquiera, se obtiene la nueva fórmula:
    $s^{2}=\displaystyle {\frac {\sum _{i=1}^{n}(x_{i}-K)^{2}-(\sum _{i=1}^{n}(x_{i}-K))^{2}/n}{n-1}}.\!$
Cuanto más cerca esté $K$ del valor medio, más preciso será el resultado, pero simplemente eligiendo un valor dentro del rango de muestras se garantizará la estabilidad deseada. Si los valores $(x_{i}-K)$ son pequeños, entonces no hay problemas con la suma de sus cuadrados, por el contrario, si son grandes, necesariamente significa que la varianza también es grande. En cualquier caso, el segundo término en la fórmula es siempre más pequeño que el primero, por lo que no puede producirse ninguna cancelación.
Si se toma solo la primera muestra como $K$, el algoritmo se puede escribir en el lenguaje de programación Python como
esta fórmula facilita también el cálculo incremental, que puede expresarse como

## Algoritmo de dos pasos

Una aproximación alternativa, usando una fórmula diferente para la varianza, computa primero la media de la muestra,
    ${\bar {x}}={\frac {\sum _{j=1}^{n}x_{j}}{n}},$
y después computa la suma de los cuadrados de las diferencias con la media,
    ${\text{sample variance}}=s^{2}=\displaystyle {\frac {\sum _{i=1}^{n}(x_{i}-{\bar {x}})^{2}}{n-1}},\!$
donde s es la desviación estándar. Este planteamiento viene dado por el siguiente pseudocódigo:
Este algoritmo es numéricamente estable si n es pequeño. Sin embargo, los resultados de estos dos algoritmos simples ("ingenuo" y "de dos pasos") pueden depender excesivamente del orden de los datos y pueden dar resultados deficientes para conjuntos de datos muy grandes, debido a repetidos errores de redondeo en la acumulación de las sumas. Técnicas como la suma compensada se pueden usar para combatir este error hasta cierto punto.

## Algoritmo en línea de Welford

A menudo es útil poder calcular la variación en una sola pasada, inspeccionando cada valor $x_{i}$ solo una vez; por ejemplo, cuando los datos se recopilan sin el almacenamiento suficiente para mantener todos los valores, o cuando los costos de acceso a la memoria dominan a los de cálculo. Para este algoritmo en línea, se utiliza una relación de recurrencia entre cantidades a partir de las cuales las estadísticas requeridas se pueden calcular de forma numéricamente estable.
Las siguientes fórmulas se pueden utilizar para actualizar la media y la varianza (estimada) de la secuencia, para un elemento adicional x$_n$. Aquí, x$_n$ denota la media muestral de las primeras n muestras (x$_1$, ..., x$_n$), s2 n su varianza muestral, y σ2 n su varianza poblacional.
    ${\bar {x}}_{n}={\frac {(n-1)\,{\bar {x}}_{n-1}+x_{n}}{n}}={\bar {x}}_{n-1}+{\frac {x_{n}-{\bar {x}}_{n-1}}{n}}\!$
    $s_{n}^{2}={\frac {n-2}{n-1}}\,s_{n-1}^{2}+{\frac {(x_{n}-{\bar {x}}_{n-1})^{2}}{n}}=s_{n-1}^{2}+{\frac {(x_{n}-{\bar {x}}_{n-1})^{2}}{n}}-{\frac {s_{n-1}^{2}}{n-1}},\quad n>1$
    $\sigma _{n}^{2}={\frac {(n-1)\,\sigma _{n-1}^{2}+(x_{n}-{\bar {x}}_{n-1})(x_{n}-{\bar {x}}_{n})}{n}}=\sigma _{n-1}^{2}+{\frac {(x_{n}-{\bar {x}}_{n-1})(x_{n}-{\bar {x}}_{n})-\sigma _{n-1}^{2}}{n}}.$
Estas fórmulas sufren de inestabilidad numérica, ya que restan repetidamente un número pequeño de un número grande que se escala con n. Una mejor cantidad para actualizar es la suma de cuadrados de las diferencias de la media actual, $\textstyle \sum _{i=1}^{n}(x_{i}-{\bar {x}}_{n})^{2}$, que aquí denota $M_{2,n}$:
    ${\begin{aligned}M_{2,n}&=M_{2,n-1}+(x_{n}-{\bar {x}}_{n-1})(x_{n}-{\bar {x}}_{n})\\[4pt]s_{n}^{2}&={\frac {M_{2,n}}{n}}\\[4pt]\sigma _{n}^{2}&={\frac {M_{2,n}}{n-1}}\end{aligned}}$
Este algoritmo fue ideado por Welford, y se ha analizado exhaustivamente. También es común denotar $M_{k}={\bar {x}}_{k}$ y $S_{k}=M_{2,k}$.
A continuación se muestra un ejemplo de implementación en Python para el algoritmo de Welford.
Este algoritmo es mucho menos propenso a la pérdida de precisión debido a la cancelación catastrófica, pero podría no ser tan eficiente debido a la operación de división incluida dentro del bucle. Para disponer de un algoritmo de dos pasos particularmente robusto con el fin de calcular la varianza, primero se puede calcular y restar una estimación de la media y luego usar este algoritmo con los residuos.
El algoritmo paralelo mostrado más adelante ilustra cómo combinar varios conjuntos de estadísticas calculadas en línea.

## Algoritmo incremental ponderado

El algoritmo puede extenderse para manejar pesos de muestra desiguales, reemplazando el simple contador n con la suma de pesos vista hasta ahora. West (1979) sugiere este algoritmo incremental:

## Algoritmo "paralelo"

Chan et al. observaron que el algoritmo en línea de Welford detallado anteriormente es un caso especial de un algoritmo que funciona para cualquier partición de la muestra $X$ en los conjuntos $X_{A}$, $X_{B}$:
    $\delta \!={\bar {x}}_{B}-{\bar {x}}_{A}$
    ${\bar {x}}_{X}={\bar {x}}_{A}+\delta \cdot {\frac {n_{B}}{n_{X}}}$
    $M_{2,X}=M_{2,A}+M_{2,B}+\delta ^{2}\cdot {\frac {n_{A}n_{B}}{n_{X}}}$.
Esto puede ser útil cuando, por ejemplo, se pueden asignar múltiples unidades de procesamiento a partes discretas de la entrada.
El método de Chan para estimar la media es numéricamente inestable cuando $n_{A}\approx n_{B}$ y ambos son grandes, porque el error numérico en ${\bar {x}}_{B}-{\bar {x}}_{A}$ no se reduce de la forma en que se encuentra en el caso $n_{B}=1$. En tales casos, es preferible ${\bar {x}}_{X}={\frac {n_{A}{\bar {x}}_{A}+n_{B}{\bar {x}}_{B}}{n_{A}+n_{B}}}$.
Esto se puede generalizar para permitir la paralelización con Extensiones Vectoriales Avanzadas (EVA), con unidades de procesamiento gráfico y agregados de computadoras, y para la covarianza.

## Ejemplo

Supóngase que todas las operaciones de punto flotante utilizan aritmética IEEE 754 de doble precisión estándar. Considérese la muestra (4, 7, 13, 16) de una población infinita. En base a esta muestra, la media poblacional estimada es 10, y la estimación no sesgada de la varianza poblacional es 30. Tanto el algoritmo "ingenuo" como el algoritmo de dos pasos calculan estos valores correctamente.
A continuación, considérese la muestra (10$^8$ + 4, 10$^8$ + 7, 10$^8$ + 13, 10$^8$ + 16), que da lugar a la misma varianza estimada que la primera muestra. El algoritmo de dos pasos calcula esta estimación de varianza correctamente, pero el algoritmo "ingenuo" devuelve 29.33333333333333332 en lugar de 30.
Si bien esta pérdida de precisión puede ser tolerable y vista como un defecto menor del algoritmo "ingenuo", un aumento adicional del desplazamiento hace que el error sea catastrófico. Considérese la muestra (10$^9$ + 4, 10$^9$ + 7, 10$^9$ + 13, 10$^9$ + 16). De nuevo, la varianza estimada de la población de 30 se calcula correctamente mediante el algoritmo de dos pasos, pero el algoritmo "ingenuo" ahora lo calcula como −170.66666666666666. Este es un problema serio con el algoritmo "ingenuo" y se debe a la cancelación catastrófica en la resta de dos números similares en la etapa final del algoritmo.

## Estadísticas de orden superior

Terriberry amplía las fórmulas de Chan para calcular el tercer y cuarto momento central, necesarios, por ejemplo, al estimar la asimetría estadística y la curtosis:
    ${\begin{aligned}M_{3,X}=M_{3,A}+M_{3,B}&+\delta ^{3}{\frac {n_{A}n_{B}(n_{A}-n_{B})}{n_{X}^{2}}}+3\delta {\frac {n_{A}M_{2,B}-n_{B}M_{2,A}}{n_{X}}}\\[6pt]M_{4,X}=M_{4,A}+M_{4,B}&+\delta ^{4}{\frac {n_{A}n_{B}\left(n_{A}^{2}-n_{A}n_{B}+n_{B}^{2}\right)}{n_{X}^{3}}}\\[6pt]&+6\delta ^{2}{\frac {n_{A}^{2}M_{2,B}+n_{B}^{2}M_{2,A}}{n_{X}^{2}}}+4\delta {\frac {n_{A}M_{3,B}-n_{B}M_{3,A}}{n_{X}}}\end{aligned}}$
Aquí, los $M_{k}$ son nuevamente las sumas de las potencias de las diferencias conrespecto a la media $\sum (x-{\overline {x}})^{k}$, dando
    ${\begin{aligned}&{\text{skewness}}=g_{1}={\frac {{\sqrt {n}}M_{3}}{M_{2}^{3/2}}},\\[4pt]&{\text{kurtosis}}=g_{2}={\frac {nM_{4}}{M_{2}^{2}}}-3.\end{aligned}}$
Para el caso incremental (es decir, $B=\{x\}$), esto se simplifica a:
    ${\begin{aligned}\delta &=x-m\\[5pt]m'&=m+{\frac {\delta }{n}}\\[5pt]M_{2}'&=M_{2}+\delta ^{2}{\frac {n-1}{n}}\\[5pt]M_{3}'&=M_{3}+\delta ^{3}{\frac {(n-1)(n-2)}{n^{2}}}-{\frac {3\delta M_{2}}{n}}\\[5pt]M_{4}'&=M_{4}+{\frac {\delta ^{4}(n-1)(n^{2}-3n+3)}{n^{3}}}+{\frac {6\delta ^{2}M_{2}}{n^{2}}}-{\frac {4\delta M_{3}}{n}}\end{aligned}}$
Al preservar el valor $\delta /n$, solo se necesita una operación de división y, por lo tanto, las estadísticas de orden superior se pueden calcular con un reducido costo incremental.
Un ejemplo del algoritmo en línea para la curtosis implementado como se describe es:
Pébaÿ extiende aún más estos resultados a momentos centrales de orden arbitrario, para los casos incrementales y por pares, y posteriormente Pébaÿ et al. lo hicieron para momentos ponderados y compuestos. También se pueden encontrar fórmulas similares para la covarianza.
Choi y Sweetman ofrecieron dos métodos alternativos para calcular la asimetría y la curtosis, cada uno de los cuales puede ahorrar importantes requisitos de memoria de computadora y tiempo de CPU en ciertas aplicaciones. El primer enfoque es calcular los momentos estadísticos separando los datos en contenedores y luego calculando los momentos a partir de la geometría del histograma resultante, que efectivamente se convierte en un algoritmo de un paso para momentos más altos. Un beneficio es que los cálculos estadísticos del momento se pueden realizar con una precisión arbitraria, de manera que se pueden ajustar a la precisión de, por ejemplo, el formato de almacenamiento de datos o el hardware de medición original. Un histograma relativo de una variable aleatoria se puede construir de manera convencional: el rango de valores potenciales es dividido en contenedores y la cantidad de ocurrencias dentro de cada contenedor se recuenta y se traza de manera tal que el área de cada rectángulo es igual a la porción de los valores de muestra dentro de ese contenedor:
    $H(x_{k})={\frac {h(x_{k})}{A}}$
donde $h(x_{k})$ y $H(x_{k})$ representan la frecuencia y la frecuencia relativa en el intervalo $x_{k}$ y $A=\sum _{k=1}^{K}h(x_{k})\,\Delta x_{k}$ es el área total del histograma. Después de esta normalización, los momentos en bruto $n$ y los momentos centrales de $x(t)$ se pueden calcular a partir del histograma relativo:
    $m_{n}^{(h)}=\sum _{k=1}^{K}x_{k}^{n}H(x_{k})\,\Delta x_{k}={\frac {1}{A}}\sum _{k=1}^{K}x_{k}^{n}h(x_{k})\,\Delta x_{k}$
    $\theta _{n}^{(h)}=\sum _{k=1}^{K}{\Bigx_{k}-m_{1}^{(h)}{\Big )}^{n}\,H(x_{k})\,\Delta x_{k}={\frac {1}{A}}\sum _{k=1}^{K}{\Bigx_{k}-m_{1}^{(h)}{\Big )}^{n}h(x_{k})\,\Delta x_{k}$
donde el superíndice $^{(h)}$ indica que los momentos se calculan a partir del histograma. Para un ancho constante del contenedor $\Delta x_{k}=\Delta x$ estas dos expresiones se pueden simplificar utilizando $I=A/\Delta x$:
    $m_{n}^{(h)}={\frac {1}{I}}\sum _{k=1}^{K}x_{k}^{n}\,h(x_{k})$
    $\theta _{n}^{(h)}={\frac {1}{I}}\sum _{k=1}^{K}{\Bigx_{k}-m_{1}^{(h)}{\Big )}^{n}h(x_{k})$
El segundo enfoque de Choi y Sweetman es una metodología analítica para combinar momentos estadísticos de segmentos individuales de un historial en el tiempo, de modo que los momentos globales resultantes sean los del historial del tiempo completo. Esta metodología podría usarse para el cálculo paralelo de momentos estadísticos con la combinación posterior de esos momentos, o para la combinación de momentos estadísticos computados en tiempos secuenciales.
Si se conocen conjuntos $Q$ de momentos estadísticos: $(\gamma _{0,q},\mu _{q},\sigma _{q}^{2},\alpha _{3,q},\alpha _{4,q})\quad$ para $q=1,2,\ldots ,Q$, entonces cada $\gamma _{n}$ puede expresarse en términos de los momentos en bruto $n$ equivalentes:
    $\gamma _{n,q}=m_{n,q}\gamma _{0,q}\qquad \quad {\textrm {para}}\quad n=1,2,3,4\quad {\text{ and }}\quad q=1,2,\dots ,Q$
donde $\gamma _{0,q}$ generalmente se toma como la duración del historial de tiempo de $q^{th}$, o el número de puntos si $\Delta t$ es constante.
La ventaja de expresar los momentos estadísticos en términos de $\gamma$ es que los conjuntos de $Q$ se pueden combinar por adición, y no hay límite superior en el valor de $Q$.
    $\gamma _{n,c}=\sum _{q=1}^{Q}\gamma _{n,q}\quad \quad {\text{para }}n=0,1,2,3,4$
donde el subíndice $_{c}$ representa el historial en el tiempo concatenado o $\gamma$ combinado. Estos valores combinados de $\gamma$ se pueden transformar inversamente en momentos sin procesar que representan el historial en el tiempo concatenado completo
    $m_{n,c}={\frac {\gamma _{n,c}}{\gamma _{0,c}}}\quad {\text{para }}n=1,2,3,4$
Relaciones conocidas entre los momentos sin procesar ($m_{n}$) y los momentos centrales ($\theta _{n}=\operatorname {E} [(x-\mu )^{n}])$) se utilizan después para calcular los momentos centrales de la historia temporal concatenada. Finalmente, los momentos estadísticos de la historia concatenada se computan a partir de los momentos centrales:
    $\mu _{c}=m_{1,c}\qquad \sigma _{c}^{2}=\theta _{2,c}\qquad \alpha _{3,c}={\frac {\theta _{3,c}}{\sigma _{c}^{3}}}\qquad \alpha _{4,c}={\frac {\theta _{4,c}}{\sigma _{c}^{4}}}-3$

## Covarianza

Se pueden usar algoritmos muy similares para calcular el covarianza.

### Algoritmo "ingenuo"

El algoritmo "ingenuo" es:
    $\operatorname {Cov} (X,Y)=\displaystyle {\frac {\sum _{i=1}^{n}x_{i}y_{i}-(\sum _{i=1}^{n}x_{i})(\sum _{i=1}^{n}y_{i})/n}{n}}.\!$
Para el algoritmo anterior, se podría usar el siguiente código de Python:

### Con estimación de la media

En cuanto a la varianza, la covarianza de dos variables aleatorias también es invariante al cambio, por lo que dados dos valores constantes $k_{x}$ y $k_{y},$ pueden escribirse:
    $\operatorname {Cov} (X,Y)=\operatorname {Cov} (X-k_{x},Y-k_{y})=\displaystyle {\frac {\sum _{i=1}^{n}(x_{i}-k_{x})(y_{i}-k_{y})-(\sum _{i=1}^{n}(x_{i}-k_{x}))(\sum _{i=1}^{n}(y_{i}-k_{y}))/n}{n}}.\!$
y nuevamente, elegir un valor dentro del rango de valores estabilizará la fórmula contra la cancelación catastrófica y lo hará más robusto contra grandes sumas. Tomando el primer valor de cada conjunto de datos, el algoritmo se puede escribir como:

### Algoritmo de dos pasos

El algoritmo de dos pasos primero calcula las medias muestrales y luego la covarianza:
    ${\bar {x}}=\displaystyle \sum _{i=1}^{n}x_{i}/n$
    ${\bar {y}}=\displaystyle \sum _{i=1}^{n}y_{i}/n$
    $\operatorname {Cov} (X,Y)=\displaystyle {\frac {\sum _{i=1}^{n}(x_{i}-{\bar {x}})(y_{i}-{\bar {y}})}{n}}.\!$
Se puede escribir como:
Una versión compensada ligeramente más precisa realiza el algoritmo "ingenuo" completamente en los residuos. Las sumas finales $\textstyle \sum x_{i}$ y $\textstyle \sum y_{i}$ deberían ser cero, pero la segunda pasada compensa cualquier pequeño error.

### Algoritmo en línea

Existe un algoritmo estable de una pasada, similar al algoritmo en línea para calcular la varianza, que calcula el momento $\textstyle C_{n}=\sum _{i=1}^{n}(x_{i}-{\bar {x}}_{n})(y_{i}-{\bar {y}}_{n})$:
    ${\begin{alignedat}{2}{\bar {x}}_{n}&={\bar {x}}_{n-1}&\,+\,&{\frac {x_{n}-{\bar {x}}_{n-1}}{n}}\\[5pt]{\bar {y}}_{n}&={\bar {y}}_{n-1}&\,+\,&{\frac {y_{n}-{\bar {y}}_{n-1}}{n}}\\[5pt]C_{n}&=C_{n-1}&\,+\,&(x_{n}-{\bar {x}}_{n})(y_{n}-{\bar {y}}_{n-1})\\[5pt]&=C_{n-1}&\,+\,&(x_{n}-{\bar {x}}_{n-1})(y_{n}-{\bar {y}}_{n})\end{alignedat}}$
La asimetría aparente en esa última ecuación se debe al hecho de que $\textstyle (x_{n}-{\bar {x}}_{n})={\frac {n-1}{n}}(x_{n}-{\bar {x}}_{n-1})$, por lo que ambos términos de actualización son iguales a $\textstyle {\frac {n-1}{n}}(x_{n}-{\bar {x}}_{n-1})(y_{n}-{\bar {y}}_{n-1})$. Se puede lograr una mayor precisión si primero se calculan las medias y luego se usa el algoritmo estable de una pasada en los residuos.
Así se puede calcular la covarianza como
    ${\begin{aligned}\operatorname {Cov} _{N}(X,Y)={\frac {C_{N}}{N}}&={\frac {\operatorname {Cov} _{N-1}(X,Y)\cdot (N-1)+(x_{n}-{\bar {x}}_{n})(y_{n}-{\bar {y}}_{n-1})}{N}}\\&={\frac {\operatorname {Cov} _{N-1}(X,Y)\cdot (N-1)+(y_{n}-{\bar {y}}_{n})(x_{n}-{\bar {x}}_{n-1})}{N}}\\&={\frac {\operatorname {Cov} _{N-1}(X,Y)\cdot (N-1)+{\frac {N-1}{N}}(x_{n}-{\bar {x}}_{n-1})(y_{n}-{\bar {y}}_{n-1})}{N}}.\end{aligned}}$
También se puede hacer una pequeña modificación para calcular la covarianza ponderada:
Del mismo modo, existe una fórmula para combinar las covarianzas de dos conjuntos que se pueden usar para paralelizar el cálculo:
    $C_{X}=C_{A}+C_{B}+({\bar {x}}_{A}-{\bar {x}}_{B})({\bar {y}}_{A}-{\bar {y}}_{B})\cdot {\frac {n_{A}n_{B}}{n_{X}}}.$

### Versión ponderada por lotes

También existe una versión del algoritmo en línea ponderado que se actualiza por lotes: haciendo que $w_{1},\dots w_{N}$ denote los pesos, se puede escribir
    ${\begin{alignedat}{2}{\bar {x}}_{n+k}&={\bar {x}}_{n}&\,+\,&{\frac {\sum _{i=n+1}^{n+k}w_{i}(x_{i}-{\bar {x}}_{n})}{\sum _{i=1}^{n+k}w_{i}}}\\{\bar {y}}_{n+k}&={\bar {y}}_{n}&\,+\,&{\frac {\sum _{i=n+1}^{n+k}w_{i}(y_{i}-{\bar {y}}_{n})}{\sum _{i=1}^{n+k}w_{i}}}\\C_{n+k}&=C_{n}&\,+\,&\sum _{i=n+1}^{n+k}w_{i}(x_{i}-{\bar {x}}_{n+k})(y_{i}-{\bar {y}}_{n})\\&=C_{n}&\,+\,&\sum _{i=n+1}^{n+k}w_{i}(x_{i}-{\bar {x}}_{n})(y_{i}-{\bar {y}}_{n+k})\\\end{alignedat}}$
La covarianza se puede calcular como
    $\operatorname {Cov} _{N}(X,Y)={\frac {C_{N}}{\sum _{i=1}^{N}w_{i}}}$