lunes, 21 de octubre de 2024

Funciones. Estadística.

Función para el cálculo de la varianza.

Ya analizamos en [esta entrada] las funciones Calc que nos permiten conocer la variabilidad de la serie o colección de datos que conforman una muestra, destacando la varianza y su derivada, la desviación típica o desviación estándar. Observamos en ella que no existen funciones integrada (Built-In) OOo Basic que nos permita realizar estos cálculos, por lo que deberemos crearlas.


El objetivo de esta entrada es desarrollar el código OOo Basic de la función que calcula la varianza de una muestra, tomando como referencia la fórmula recogida ya en [la entrada] referida a la función Calc equivalente y que reproduzco a continuación:


En cuanto al significado de la fórmula, diremos que la varianza es una unidad promedio de las diferencias entre los valores de la muestra y su media; al elevar este resultado al cuadrado se elimina el efecto de reducción del valor que en el sumatorio tendrían las sumas de valores positivos y negativos. El denominador (n-1) diferencia la fórmula del cálculo del valor muestral del cálculo del valor poblacional (N), en el que no se efectúa esa resta.

En términos de creación de la función OOo Basic, deberemos observar que la varianza (s2) es resultado del sumatorio de las diferencias entre los valores observados y la media aritmética de la muestra, lo que implica que deberemos haber calculado previamente dicho estadístico. También deberemos elevar esos valores al cuadrado y identificar el valor de n (número de observaciones), aunque en este caso, dado que se trata de calcular el estadístico muestral, lo que nos interesa calcular es n-1.

A pesar de las diferencia conceptuales y estadísticas entre media y varianza, en términos de desarrollo del algoritmo de la función, los planteamientos empleados en la función de cálculo de la media nos van a ser útiles para crear esta segunda función. 

De hecho, la primera decisión que deberemos tomar es si creamos una función que calcule la media o si utilizamos la función ya creada desde la nueva, ahorrándonos trabajo y complejidad en la función actual.

Aplicando el principio de modularidad, la respuesta es la segunda opción, pero no siempre resulta funcional, ya que obligamos al usuario de contar con ambas y a relacionarlas. De hecho, en Calc, al menos aparentemente (1), se adopta el criterio de resolver ambos cálculos en una única función, evitando así tener que recurrir al cálculo previo del promedio. 

Por  motivos de funcionalidad, esta segunda opción será la que se asuma en nuestra propuesta, lo que incluye reutilizar el código de la función que calcula el promedio. No obstante, en la explicación de la función de cálculo de la varianza omitiré la explicación de lo que se refiere al de la media aritmética. Para ésta remito a la explicación dada en [la entrada] en que se expone esa función.

Function fVarianza(ByRef mDatos() As Object) As Double

Dim vSum As Long
Dim vCuad As Double, vSumCuad As Double
dim vN As Integer, i As Integer
Dim vMed As Double, vVarianza As Double

'Calculo del promedio

vSum = 0
vN = 0

For i = 0 To UBound(mDatos())
vSum = vSum + mDatos(i)
vN = i
Next

vN = vN + 1
vMed = vSum/vN

'Cálculo de la varianza

vCuad = 0
vSumCuad = 0

For i = 0 To UBound(mDatos())
vCuad = ((mDatos(i)-vMed)^2)
vSumCuad = vSumCuad + vCuad
Next

vVarianza = vSumCuad/(vN-1)

fVarianza = vVarianza

End Function

Es importante que nos fijemos en las variables privadas de la función que tienen que ver con el cálculo de la varianza: todas estas variables (vCuad, vSumCuad vVarianza) han sido declaradas como variables de tipo Double, ya que los cálculos que vamos a realizar requieren este tipo de variable numérica decimal, al tomar como referencia un valor también de tipo (vMed). Si no empleamos una tipología de número decimal, obtendremos un resultado aparentemente correcto, pero estará sesgado si nuestro tipo no incluye valores decimales (por ejemplo, si empleamos el tipo Long), generando un error difícil de localizar y de corregir en algoritmos complejos que empleen nuestra función.

Dicho esto, el modo de realizar el sumatorio de las diferencias entre los valores y la media, elevándolos al cuadrado (2) se resuelve de nuevo con un bucle que recorre la matriz de datos, sobre la que se realiza el sumatorio que, en este caso, incluye una operación (((mDatos(i)-vMed)^2)). Obsérvese que hemos diferenciado la operación (vCuad = ((mDatos(i)-vMed)^2)) del sumatorio propiamente dicho (vSumCuad = vSumCuad + vCuad), dado que trabajamos con dos variables que se complementan (vCuad y vSumCuad). Esto es así por motivos didácticos y de claridad en la formulación del algoritmo, pero podríamos haber trabajado con una única variable y resulto el procedimiento con una única instrucción, sin que se viera afectado el cálculo (v.g. vSumCuad = vSumCuad + ((mDatos(i)-vMed)^2)).

El divisor (vN-1) se ajusta a lo establecido en la fórmula de la varianza de la muestra, aprovechando el valor establecido en vN en el cálculo de la media, aunque cabrían otras opciones (3). Lo que conlleva la opción adoptada es que la resta n-1 sea encuadrada entre paréntesis, ya que, de no ser así, por la primacía de los operadores, primero se realizaría la división vSumCuad/vN y después se restaría -1, algo que evidentemente no nos interesa ya que da lugar a un resultados erróneo (4).


NOTAS

(1) Por apariencia entiendo aquí los datos que se solicitan en la fórmula Calc, que se limitan a la matriz de los valores muestrales.
(2) Tal y como se recoge en la fórmula de la varianza y por las razones que se explican en el texto de la entrada.
(3) Por ejemplo, utilizar como divisor el resultado de la función UBound(mDatos()), lo que ahorraría el uso de la variable vN y aprovecharía el hecho de que ese resultado se ajuste a la fórmula n-1.
(4) En el cálculo de la media esto no sucede porque previamente al uso de vN como divisor del sumatorio de datos, procedemos a modificar esa variable (vN = vN + 1 -> vMed = vSum/vN). También podríamos proceder del mismo modo en el cálculo de la varianza; pero he preferido ejemplarizar los dos modos de proceder.