4. Transformaciones de BoxCox

Autor/a

Rubén Cool

1 Introducción

En el análisis de regresión lineal simple, el modelo se asume de la forma: \[Y = \beta_0 + \beta_1 X + \epsilon\] Para que las inferencias (pruebas de hipótesis, intervalos de confianza y predicciones) sean válidas, los errores (\(\epsilon_i\)) deben cumplir con los supuestos fundamentales: normalidad, homocedasticidad (varianza constante) e independencia.

Cuando estos supuestos no se cumplen, frecuentemente evidenciados por curvaturas en los gráficos de dispersión o embudos en los residuales, la transformación de Box-Cox ofrece una herramienta formal de máxima verosimilitud para encontrar la potencia óptima \(\lambda\) en la variable respuesta \(Y\) que restaure los supuestos del modelo.

2 Transformación de BoxCox

Sea \(y_i\) la variable de respuesta positiva. La transformación de Box-Cox se define como:

\[\begin{equation} y_{i}^{(\lambda)} = \begin{cases} \frac{y_{i}^{\lambda} - 1}{\lambda}, & \text{si } \lambda \neq 0 \\ \ln(y_i), & \text{si } \lambda = 0 \end{cases} \end{equation}\]

La transformación Box-Cox proporciona un método formal para encontrar el valor de \(\lambda\) que mejor normaliza los datos (solo funciona con datos positivos \(y_i>0\)).

El valor de \(\lambda\) se determina mediante estimación de máxima verosimilitud del modelo transformado para encontrar el valor que aproxime lo máximo posible la distribución normal de los datos.

\[L^{(\lambda)}=-\frac{n}{2}ln(\hat \sigma^2_{(\lambda)}) + (\lambda-1)\displaystyle \sum_{i=1}^nln(y_i)\]

El valor de \(\lambda\) encontrado dice qué transformación se está aplicando. A menudo se redondea al valor “común” más cercano para facilitar la interpretación.

\[\lambda \in [-5,5]\]

2.1 Transformaciones comúnes

\(\lambda\) Transformación
-3 \[\frac{1}{Y^3}\]
-2 \[\frac{1}{Y^2}\]
-1 \[\frac{1}{Y}\]
-0.5 \[\frac{1}{\sqrt Y}\]
0 \[ln(Y)\]
0.5
1 \[\sqrt Y\]
2 \[Y^2\]
3 \[Y^3\]

  • Box-Cox no es robusto ante valores atípicos.

  • Se aplica principalmente a la transformación de la variable respuesta \(Y\).

  • Todos los valores de la variable a transformar deberán ser positivos.

  • Después de aplicar el método es importante verificar de nuevo los supuestos del modelo.

  • No usar el método si se cumplen los supuestos del modelo.

Es posible encontrar un IC aproximado para el parámetro de transformación \(\lambda\). Este IC puede ser útil para seleccionar el valor final de \(\lambda\).

Un intervalo de confianza aproximado del \(100(1−α)\%\) para \(\lambda\) se define como el conjunto de valores que cumplen:

\[L(\hat \lambda)-L(\lambda)\leq \frac{1}{2} \chi^2_{\alpha,1}\]

  • \(\lambda\) El parámetro de la transformación de potencia de Box-Cox.

  • L(𝜆) Log-Verosimilitud.

  • \(\hat\lambda\) Estimación puntual (EMV).

  • \(L_{max}(\lambda)-\frac{1}{2} \chi^2_{\alpha,1}\) Es el umbral para construir un intervalo de confianza.

  • \(\lambda_1\) Es el límite inferior para el Intervalo de Confianza.

  • \(\lambda_2\) Es el límite superior para el Intervalo de Confianza.

A pesar del valor que minimiza la suma de cuadrados de los residuos es \(\hat \lambda\), los valores que se encuentran entre \(𝜆_1\) y \(𝜆_2\) podrían utilizarse de forma eficiente para realizar una transformación.

  1. Un valor de \(\lambda\) de 1 es equivalente a utilizar los datos originales. Por lo tanto, si el intervalo de confianza de λ óptimo incluye 1, entonces no es necesaria una transformación.

  2. Si incluye 0, el logaritmo natural puede considerarse una buena transformación.

  3. Si está “alejado” de 0 y 1, los datos necesitan una transformación de potencia específica.

3 Ejemplo 1

Estaremos siguiendo los siguientes pasos para obtener un modelo optimo en los dos ejemplos:

1. Descripción de los datos.

2. Determinar modelo inicial.

3. Revisión de supuestos.

4. Determinar la lambda estimada óptima para la transformación Box-Cox.

5. Determinar modelo con la transformación.

6. Revisión de supuestos.

7. Comparación entre modelos. Nota: Para todas las pruebas de hipótesis se usará un nivel de significancia del 0.05

Para este laboratorio utilizaremos R y el paquete MASS, que incluye la función boxcox().

# Cargar librerías necesarias 
library(MASS) 
library(ggplot2)
library(mosaic) 
library(knitr)
library(kableExtra)
library(modeest) # Necesario para la función mfv()
library(e1071)
library(nortest)
library(lmtest)
library(alr4)
x_kwh <- c(679, 292, 1012, 493, 582, 1156, 997, 2189, 1097, 2078, 1818, 1700, 747, 2030, 1643, 414, 354, 1276, 745, 435, 540, 874, 1543, 1029, 710, 1434, 
           837, 1748, 1381, 1428, 1255, 1777, 370, 2316, 1130, 463, 770, 724, 808, 790, 783, 406, 1242, 658, 1746, 468, 1114, 413, 1787, 3560, 1495, 2221, 1526)

y_kw <- c(0.79, 0.44, 0.56, 0.79, 2.70, 3.64, 4.73, 9.50, 5.34, 6.85, 5.84, 5.21, 3.25, 4.43, 3.16, 0.50, 0.17, 1.88, 0.77, 1.39, 0.56, 1.56, 5.28, 0.64, 4.00, 0.31,
          4.20, 4.88, 3.48, 7.58, 2.63, 4.99, 0.59, 8.19, 4.79, 0.51, 1.74, 4.10, 3.94, 0.96, 3.29, 0.44, 3.24, 2.14, 5.71, 0.64, 1.90, 0.51, 8.33, 14.94, 5.11, 3.85, 3.93)

# Crear el data frame
datos_electricos <- data.frame(X = x_kwh, Y = y_kw)

# Primeras observaciones
head(datos_electricos)
     X    Y
1  679 0.79
2  292 0.44
3 1012 0.56
4  493 0.79
5  582 2.70
6 1156 3.64
modelo_original <- lm(Y ~ X, data = datos_electricos)
summary(modelo_original)

Call:
lm(formula = Y ~ X, data = datos_electricos)

Residuals:
    Min      1Q  Median      3Q     Max 
-4.1399 -0.8275 -0.1934  1.2376  3.1522 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.8313037  0.4416121  -1.882   0.0655 .  
X            0.0036828  0.0003339  11.030 4.11e-15 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 1.577 on 51 degrees of freedom
Multiple R-squared:  0.7046,    Adjusted R-squared:  0.6988 
F-statistic: 121.7 on 1 and 51 DF,  p-value: 4.106e-15
## Diagnóstico inicial
plot(y_kw ~ x_kwh, data = datos_electricos)

plot(modelo_original)

Observa la dispersión de los residuales y busca curvatura, patrones sistemáticos y posibles observaciones influyentes.

3.1 Supuesto de Normalidad de los residuales

3.1.1 Planteamiento de las Hipótesis

Para cualquier prueba de normalidad sobre los residuales del modelo (\(\varepsilon_i\)):

  • \(\text{H}_0\) (Hipótesis Nula): Los residuales del modelo siguen una distribución normal (\(\varepsilon_i \sim N(0, \sigma^2)\)).

  • \(\text{H}_1\) (Hipótesis Alternativa): Los residuales del modelo no siguen una distribución normal.

shapiro.test(modelo_original$residuals)

    Shapiro-Wilk normality test

data:  modelo_original$residuals
W = 0.97435, p-value = 0.3087

Como \(p\text{-valor}=0.3087 > 0.05\) no se rechaza \(\text{H}_0\). No existen evidencias de que los residuales no se distribuyen de forma normal.

3.2 Supuesto de Homocedasticidad

3.2.1 Planteamiento de las Hipótesis

  • \(\text{H}_0\) (Hipótesis Nula): Los residuales son homocedásticos (la varianza de los errores es constante, \(\sigma_i^2 = \sigma^2\)).

  • \(\text{H}_1\) (Hipótesis Alternativa): Los residuales son heterocedásticos (la varianza de los errores no es constante).

# 2. Prueba formal de Breusch-Pagan
prueba_bp <- bptest(modelo_original)
print(prueba_bp)

    studentized Breusch-Pagan test

data:  modelo_original
BP = 6.8012, df = 1, p-value = 0.00911

Como \(p\text{-valor}=0.0091 < 0.05\) se rechaza \(\text{H}_0\). Los residuales son heterocedásticos (la varianza de los errores no es constante).

3.3 Supuesto de Independencia

3.3.1 Planteamiento de las Hipótesis

Para la prueba de Durbin-Watson:

  • \(\text{H}_0\) (Hipótesis Nula): \(\rho = 0\) (Los errores son independientes / No existe autocorrelación en los residuales).

  • \(\text{H}_1\) (Hipótesis Alternativa): \(\rho \neq 0\) (Existe autocorrelación en los residuales).

# 2. Prueba de Durbin-Watson
prueba_dw <- dwtest(modelo_original)
print(prueba_dw)

    Durbin-Watson test

data:  modelo_original
DW = 2.0946, p-value = 0.6262
alternative hypothesis: true autocorrelation is greater than 0
# 3. Gráfico de autocorrelación (ACF) y residuales en función del orden
datos_indep <- data.frame(
  Orden = 1:nrow(datos_electricos),
  Residuales = residuals(modelo_original)
)

# Gráfico de residuales seguidos por orden de observación
ggplot(datos_indep, aes(x = Orden, y = Residuales)) +
  geom_point(color = "#2b5c8f", size = 2.5) +
  geom_line(color = "#2b5c8f", linetype = "dashed", alpha = 0.5) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "#d9534f", linewidth = 1) +
  labs(
    title = "Residuales por Orden de Observación",
    subtitle = "Evaluación de Independencia de Errores",
    x = "Orden de la Observación",
    y = "Residuales"
  ) +
  theme_minimal()

Como Si \(p\text{-valor} > 0.05\): No se rechaza \(\text{H}_0\). Se cumple el supuesto de independencia.

3.4 Transformación de CoxBox

# Calcular Box-Cox
bc <- boxcox(modelo_original, lambda = seq(-2, 2, by = 0.1))

# Encontrar el lambda óptimo exacto
lambda_optimo <- bc$x[which.max(bc$y)]
cat("El valor óptimo estimado de lambda es:", lambda_optimo, "\n")
El valor óptimo estimado de lambda es: 0.5454545 

Aplicaremos la transformación sugerida (raíz cuadrada):

# Aplicamos transformación raíz cuadrada (lambda = 0.5) o logarítmica según el resultado de Box-Cox
# Usaremos transformación logarítmica si lambda está cerca de 0, o raíz cuadrada si está cerca de 0.5
# Para este caso de estudio eléctrico, probemos con log(Y) o raíz de Y:
datos_electricos$Y_trans <- (datos_electricos$Y)^0.5

modelo_trans <- lm(Y_trans ~ X, data = datos_electricos)
summary(modelo_trans)

Call:
lm(formula = Y_trans ~ X, data = datos_electricos)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.39185 -0.30576 -0.03875  0.25378  0.81027 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 5.822e-01  1.299e-01   4.481 4.22e-05 ***
X           9.529e-04  9.824e-05   9.699 3.61e-13 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.464 on 51 degrees of freedom
Multiple R-squared:  0.6485,    Adjusted R-squared:  0.6416 
F-statistic: 94.08 on 1 and 51 DF,  p-value: 3.614e-13
shapiro.test(modelo_trans$residuals)

    Shapiro-Wilk normality test

data:  modelo_trans$residuals
W = 0.96602, p-value = 0.1353
prueba_bp <- bptest(modelo_trans)
print(prueba_bp)

    studentized Breusch-Pagan test

data:  modelo_trans
BP = 0.012597, df = 1, p-value = 0.9106
prueba_dw <- dwtest(modelo_trans)
print(prueba_dw)

    Durbin-Watson test

data:  modelo_trans
DW = 2.3042, p-value = 0.8642
alternative hypothesis: true autocorrelation is greater than 0
## Diagnóstico inicial
plot(y_kw ~ x_kwh, data = datos_electricos)

plot(Y_trans ~ x_kwh, data = datos_electricos)

plot(modelo_trans)

3.5 Detección de Outliers

n <- nrow(datos_electricos)
p <- 2 # Intercepto y pendiente

# 1. Leverage
hat_vals <- hatvalues(modelo_trans)
umbral_hat <- 3 * (p / n)

# 2. Distancia de Cook
cook_vals <- cooks.distance(modelo_trans)
umbral_cook <- 4 / (n - p)

# 3. RStudent
r_student <- rstudent(modelo_trans)

# Identificar filas problemáticas
atipicos_rstudent <- which(abs(r_student) > 3)
atipicos_cook <- which(cook_vals > umbral_cook)

cat("Observaciones con RStudent > 3:", atipicos_rstudent, "\n")
Observaciones con RStudent > 3: 26 
plot(modelo_trans, which = 4, col = "blue", pch = 16)
abline(h = umbral_cook, col = "red", lty = 2)

# Identificamos y filtramo (la de mayorCook)
electric_filtrado <- datos_electricos[-atipicos_rstudent, ]
electric_filtrado
      X     Y   Y_trans
1   679  0.79 0.8888194
2   292  0.44 0.6633250
3  1012  0.56 0.7483315
4   493  0.79 0.8888194
5   582  2.70 1.6431677
6  1156  3.64 1.9078784
7   997  4.73 2.1748563
8  2189  9.50 3.0822070
9  1097  5.34 2.3108440
10 2078  6.85 2.6172505
11 1818  5.84 2.4166092
12 1700  5.21 2.2825424
13  747  3.25 1.8027756
14 2030  4.43 2.1047565
15 1643  3.16 1.7776389
16  414  0.50 0.7071068
17  354  0.17 0.4123106
18 1276  1.88 1.3711309
19  745  0.77 0.8774964
20  435  1.39 1.1789826
21  540  0.56 0.7483315
22  874  1.56 1.2489996
23 1543  5.28 2.2978251
24 1029  0.64 0.8000000
25  710  4.00 2.0000000
27  837  4.20 2.0493902
28 1748  4.88 2.2090722
29 1381  3.48 1.8654758
30 1428  7.58 2.7531800
31 1255  2.63 1.6217275
32 1777  4.99 2.2338308
33  370  0.59 0.7681146
34 2316  8.19 2.8618176
35 1130  4.79 2.1886069
36  463  0.51 0.7141428
37  770  1.74 1.3190906
38  724  4.10 2.0248457
39  808  3.94 1.9849433
40  790  0.96 0.9797959
41  783  3.29 1.8138357
42  406  0.44 0.6633250
43 1242  3.24 1.8000000
44  658  2.14 1.4628739
45 1746  5.71 2.3895606
46  468  0.64 0.8000000
47 1114  1.90 1.3784049
48  413  0.51 0.7141428
49 1787  8.33 2.8861739
50 3560 14.94 3.8652296
51 1495  5.11 2.2605309
52 2221  3.85 1.9621417
53 1526  3.93 1.9824228
# Reajustar modelo sin el outlier
modelo_filtrado <- lm(Y_trans ~ X, data = electric_filtrado)
summary(modelo_filtrado)

Call:
lm(formula = Y_trans ~ X, data = electric_filtrado)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.82253 -0.29841 -0.06996  0.26894  0.77846 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 5.884e-01  1.188e-01   4.952 8.76e-06 ***
X           9.708e-04  8.998e-05  10.789 1.17e-14 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.4243 on 50 degrees of freedom
Multiple R-squared:  0.6995,    Adjusted R-squared:  0.6935 
F-statistic: 116.4 on 1 and 50 DF,  p-value: 1.174e-14
shapiro.test(modelo_filtrado$residuals)

    Shapiro-Wilk normality test

data:  modelo_filtrado$residuals
W = 0.96105, p-value = 0.08691
prueba_bp <- bptest(modelo_filtrado)
print(prueba_bp)

    studentized Breusch-Pagan test

data:  modelo_filtrado
BP = 0.43153, df = 1, p-value = 0.5112
prueba_dw <- dwtest(modelo_filtrado)
print(prueba_dw)

    Durbin-Watson test

data:  modelo_filtrado
DW = 1.854, p-value = 0.2869
alternative hypothesis: true autocorrelation is greater than 0