ACTIVIDAD: INFORME DE REGRESION MULTIPLE

1.- CASO MOLUSCOS EN 3 TIPOS DE CONCENTRACIONES DE AGUA DE MAR

Dos tipos de moluscos A y B fueron sometidos a tres concentraciones distintas de agua de mar (100%, 75% y 50%) y se observó el consumo de oxígeno midiendo la concentración de O2 por unidad de peso seco del molusco.

# Librerías necesarias
library(readxl)
library(psych)
require(ggplot2)
require(plotly)
require(CGPfunctions)



# Cargue de los datos
load("moluscos.RData")
BD_moluscos$c_agua <- factor(BD_moluscos$c_agua)
BD_moluscos$molusco <- factor(BD_moluscos$molusco)
datos_moluscos= data.frame(BD_moluscos)

# Breve exploración de indicadores estadísticos de los datos
summary(BD_moluscos)
##  c_agua   molusco     cons_o      
##  50 :16   A:24    Min.   : 1.800  
##  75 :16   B:24    1st Qu.: 6.312  
##  100:16           Median : 9.700  
##                   Mean   : 9.305  
##                   3rd Qu.:11.232  
##                   Max.   :18.800
describe(BD_moluscos)
vars n mean sd median trimmed mad min max range skew kurtosis se
c_agua* 1 48 2.000000 0.8251370 2.0 2.00000 1.482600 1.0 3.0 2 0.0000000 -1.5618490 0.1190983
molusco* 2 48 1.500000 0.5052912 1.5 1.50000 0.741300 1.0 2.0 1 0.0000000 -2.0412326 0.0729325
cons_o 3 48 9.304792 3.6826517 9.7 9.15325 4.544169 1.8 18.8 17 0.3948181 -0.3076261 0.5315450

A.- Exploración de los datos

Realice un análisis exploratorio que permita conocer como es el consumo de oxígeno en las distintas concentraciones de agua de mar. Y si estas conclusiones son las mismas para cada tipo de molusco.

Se recurre a un gráfico de cajas y bigotes para realizar el análisis bivariado que permita comprender el comportamiento de los dos tipos de moluscos (A y B) en los tres tipos de concentraciones de agua de mar (50%, 75%, 100%).
Se observa que con una concentración de 50% agua de mar es cuando mas se consume oxígeno. Y en este escenario el molusco tipo B es el que mas consume.
Por otro lado, en las concentraciones de 75% y 100% de agua de mar se observa que el consumo de oxigeno es menor en ambos tipos de molusco con respecto a al 50% de agua de mar. En estos dos escenarios el molusco tipo A consume mas oxígeno que el B.

Se puede concluir que aunque la concentración de agua de mar influye en el consumo de oxígeno en los moluscos, con este gráfico no podemos establecer que en términos generales (toda la muestra) exista una estricta correlación negativa porque con una concentración de 100% de agua de mar los moluscos consumen mas oxigeno que con el 75% de concentración.

graf_1=ggplot(BD_moluscos,aes(x= c_agua, y=cons_o, fill=molusco))+  geom_boxplot()+ theme_bw()+ geom_point(position=position_jitterdodge(),alpha=0.3)+   ggtitle("Consumo de Oxígeno vs tipo de molusco y concentración de agua de mar")+   scale_x_discrete("% Concentración de agua de mar")+  scale_y_continuous("Consumo de Oxígeno")
graf_1

Veamos a continuación mejor este comportamiento con dos diagramas de cajas y bigotes desagregados: El primero muestra el consumo de oxigeno versus el tipo de moluscos. Permite observar que en términos generales (toda la muestra) el molusco A consume un poco mas de oxígeno que el molusco B; pero esta diferencia no es significativa. Si es posible observar con mayor claridad, que el molusco B presenta mayor variación en el consumo de oxígeno.

En el segundo gráfico, se puede observar que si existe una variación apreciable entre el consumo de oxigeno y los tipos de concentración de agua de mar.

graf_2=ggplot(BD_moluscos,aes(x= molusco, y=cons_o, fill=molusco))+  geom_boxplot()+ theme_bw()+ geom_point(position=position_jitterdodge(),alpha=0.3)+   ggtitle("Consumo de Oxígeno vs tipo de molusco")+   scale_x_discrete("Tipo de molusco")+  scale_y_continuous("Consumo de Oxigeno")
graf_2

graf_3=ggplot(BD_moluscos,aes(x= c_agua, y=cons_o, fill=c_agua))+  geom_boxplot()+ theme_bw()+ geom_point(position=position_jitterdodge(),alpha=0.3)+   ggtitle("Consumo de Oxígeno vs Concentración de agua de mar")+   scale_x_discrete("Tipo de molusco")+  scale_y_continuous("Consumo de Oxígeno")
graf_3

Veamos ahora como están correlacionadas las variables del conjunto de datos.
Se observa que existe una baja correlación negativa,\(R = -0.19\), entre la variable respuesta \(cons\text{_}o\) (consumo de oxígeno) y la variable \(molusco\). Se observa una correlación negativa mas elevada,\(R = -0.45\), entre la variable respuesta \(cons\text{_}o\) y la variable \(c\text{_}o\) (concentración de agua). Esto es coherente con lo encontrado en los gráficos anteriores.

datos_submol <- transform(datos_moluscos,molusco = as.numeric(molusco), c_agua=as.numeric(c_agua))

round(cor(x = datos_submol, method = "pearson"), 3)
##         c_agua molusco cons_o
## c_agua   1.000   0.000 -0.401
## molusco  0.000   1.000 -0.191
## cons_o  -0.401  -0.191  1.000
library(GGally)
ggpairs(datos_submol, columns=c("c_agua", "molusco", "cons_o"), columnLabels = c("C_agua", "Molusco", "Cons_o"), lower = list(continuous = "smooth"), diag = list(continuous = "barDiag"), axisLabels = "none")

B.- Estimación del modelo

Estime el modelo de diseño de experimentos el cual permita evaluar el efecto de la concentración de agua de mar y los tipos de molusco sobre el consumo de oxígeno. Interprete los coeficientes del modelo, el valor p y realice un post anova de considerarlo necesario para los factores.

Planteamos un test correlación de Pearson un poco mas detallado con un nivel \(\alpha=0.05\) para verificar la correlación y el grado de significancia entre las variables respuesta y los dos predictores.
Planteando las siguientes hipótesis:
Hipótesis Nula \(H0 = \text{Las variables no tienen correlación alguna}\).
Hipótesis alternativa \(H1 = \text{Las variables tienen correlación }\).

El resultado de los test muestran efectivamente un \(p-valor=0.19\) elevado para la correlación entre la variable respuesta ‘consumo de oxígeno’ y el predictor ‘molusco’. Por lo que aquí la variable nula \(H0\) NO se rechaza, pues se ha encontrado que no tienen correlación estas dos variables.
Para el caso del test de correlación entre la variable respuesta ‘consumo de oxigeno’ y el predictor ‘concentración de agua’, el \(p-valor=0.004\) es muy bajo frente al \(\alpha=0.05\) convencional . Por lo en este caso SI es posible rechazar la hipótesis nula planteada.

cor.test(x=datos_submol$molusco,y=datos_submol$cons_o,alternative="two.sided",conf.level=0.95,method="pearson")
## 
##  Pearson's product-moment correlation
## 
## data:  datos_submol$molusco and datos_submol$cons_o
## t = -1.3189, df = 46, p-value = 0.1937
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.45058673  0.09859081
## sample estimates:
##        cor 
## -0.1908913
cor.test(x=datos_submol$c_agua,y=datos_submol$cons_o,alternative="two.sided",conf.level=0.95,method="pearson")
## 
##  Pearson's product-moment correlation
## 
## data:  datos_submol$c_agua and datos_submol$cons_o
## t = -2.9689, df = 46, p-value = 0.004734
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.6150552 -0.1318910
## sample estimates:
##        cor 
## -0.4009984

Teniendo en cuenta la etapa de exploración de los datos, a continuación se plantea un Modelo de Regresión Lineal Múltiple. Se incluirán los dos predictores para efectos de verificar los resultados, y tomar decisiones para los pasos posteriores.

En el modelo se puede observar que en efecto, la variable “tipo de molusco” tiene poca correlación con la variable respuesta. Esto lo confirma el \(p-valor=0.15985\) elevado y lo que implica que esta variable pierde significancia en el modelo.

Posteriormente se aplicó un análisis de varianza (ANOVA) y se confirma el resultado: la variable “tipo de molusco” no presenta correlación con la variable respuesta “consumo de oxigeno”

modelo=lm(cons_o~c_agua+molusco,data=datos_submol)
summary(modelo)
## 
## Call:
## lm(formula = cons_o ~ c_agua + molusco, data = datos_submol)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -6.8092 -2.2945 -0.6798  2.8297  7.3011 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  14.9710     1.9469   7.690 9.78e-10 ***
## c_agua       -1.7897     0.5961  -3.002  0.00436 ** 
## molusco      -1.3913     0.9734  -1.429  0.15985    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3.372 on 45 degrees of freedom
## Multiple R-squared:  0.1972, Adjusted R-squared:  0.1616 
## F-statistic: 5.528 on 2 and 45 DF,  p-value: 0.007132
anova(modelo)
Df Sum Sq Mean Sq F value Pr(>F)
c_agua 1 102.49540 102.49540 9.013877 0.0043619
molusco 1 23.22692 23.22692 2.042673 0.1598464
Residuals 45 511.68808 11.37085 NA NA
#par(mfrow=c(2,2))
#plot(modelo)

Así pues, con base en los resultados del paso anterior se plantea un modelo de regresión solo con el predictor “concentración de agua”.

modelo_1=lm(cons_o~c_agua,data=datos_submol)
summary(modelo_1)
## 
## Call:
## lm(formula = cons_o ~ c_agua, data = datos_submol)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -7.5048 -2.1248 -0.4748  2.3504  7.7055 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  12.8842     1.3022   9.894 5.71e-13 ***
## c_agua       -1.7897     0.6028  -2.969  0.00473 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3.41 on 46 degrees of freedom
## Multiple R-squared:  0.1608, Adjusted R-squared:  0.1426 
## F-statistic: 8.814 on 1 and 46 DF,  p-value: 0.004734
par(mfrow=c(2,2))
plot(modelo_1)

Puesto que el Coeficiente de Determinación del modelo \(R^2=0.14\) es bajo, y el gráfico de residuos presenta cierto sesgo que indica que la varianza no es constante; en este punto se plantea la aplicación de un test post-Anova para mejorar la comprensión de la variación del predictor “concentración de agua”.

require(agricolae)
postAnova=LSD.test(modelo_1, "c_agua")
postAnova
## $statistics
##    MSerror Df     Mean       CV  t.value      LSD
##   11.62859 46 9.304792 36.64855 2.012896 2.426832
## 
## $parameters
##         test p.ajusted name.t ntr alpha
##   Fisher-LSD      none c_agua   3  0.05
## 
## $means
##     cons_o      std  r       LCL       UCL  Min  Max    Q25    Q50     Q75
## 1 12.25062 3.199643 16 10.534596 13.966654 6.38 18.8 10.085 11.455 14.5000
## 2  6.99250 2.804093 16  5.276471  8.708529 1.80 13.2  5.200  6.430  8.7675
## 3  8.67125 3.000940 16  6.955221 10.387279 3.68 14.0  6.140  8.595 10.5750
## 
## $comparison
## NULL
## 
## $groups
##     cons_o groups
## 1 12.25062      a
## 3  8.67125      b
## 2  6.99250      b
## 
## attr(,"class")
## [1] "group"

El resultado indica que con la “concentración de agua de mar” del 50% el “consumo promedio de oxígeno” se aleja bastante de las otras dos tipos de concentración de agua de mar de 75% y 100%. De hecho, estas dos últimos tipo de contradicción de agua de mar no difieren mucho entre si, el test post-Anova las ubica en el grupo ‘b’.

Dado que el poder de predictibilidad de este modelo de regresión es bajo (\(R^2=0.1426\)), a continuación se plantea el siguiente modelo que incluye la interacción de las dos variables predictoras y su efecto en la variable respuesta [1]:

\(y_{ij}=\mu + \beta_i + \lambda_j + (\beta\lambda)_{ij} + \epsilon_{ij}\)

modelo_2 <- lm(BD_moluscos$cons_o ~ BD_moluscos$c_agua + BD_moluscos$molusco + (BD_moluscos$c_agua*BD_moluscos$molusco))

summary(modelo_2)
## 
## Call:
## lm(formula = BD_moluscos$cons_o ~ BD_moluscos$c_agua + BD_moluscos$molusco + 
##     (BD_moluscos$c_agua * BD_moluscos$molusco))
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -5.946 -1.736 -0.710  2.237  6.625 
## 
## Coefficients:
##                                            Estimate Std. Error t value Pr(>|t|)
## (Intercept)                                 12.1750     1.0466  11.633 1.02e-14
## BD_moluscos$c_agua75                        -4.2850     1.4800  -2.895  0.00599
## BD_moluscos$c_agua100                       -2.2387     1.4800  -1.513  0.13787
## BD_moluscos$moluscoB                         0.1513     1.4800   0.102  0.91909
## BD_moluscos$c_agua75:BD_moluscos$moluscoB   -1.9462     2.0931  -0.930  0.35777
## BD_moluscos$c_agua100:BD_moluscos$moluscoB  -2.6813     2.0931  -1.281  0.20722
##                                               
## (Intercept)                                ***
## BD_moluscos$c_agua75                       ** 
## BD_moluscos$c_agua100                         
## BD_moluscos$moluscoB                          
## BD_moluscos$c_agua75:BD_moluscos$moluscoB     
## BD_moluscos$c_agua100:BD_moluscos$moluscoB    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.96 on 42 degrees of freedom
## Multiple R-squared:  0.4226, Adjusted R-squared:  0.3539 
## F-statistic: 6.149 on 5 and 42 DF,  p-value: 0.0002324


A continuación se presenta la gráfica de interacción entre las variables del modelo.

interaction.plot(x.factor = BD_moluscos$c_agua, # variable del eje x 
                 trace.factor = BD_moluscos$molusco, # variable para líneas 
                 response = BD_moluscos$cons_o, # variable del eje y 
                 fun = median, # métrica para trazar
                 ylab = "concentracion de oxigeno",
                 xlab = "concentracion de agua de mar",
                 col = c ("red", "blue"),
                 lty = 1, # tipo de línea 
                 lwd = 2, # ancho de línea
                 trace.label = "Tipo Molusco")

2.- CASO: CARACTERISTICAS DEL SUELO Y LA PRODUCCION DE BIOMASA DE UNA PLANTA FORRAJERA

Para estudiar la relación entre ciertas características del suelo y la producción de biomasa (gr) de una planta forrajera natural se obtuvieron 45 muestras en diferentes ambientes, y en cada muestra se estimó la biomasa (respuesta Y) y se registraron las características (covariables X) del suelo en el que crecía (pH, Salinidad, Zinc y Potasio).

# Cargue de los datos
load("Salinidad.RData")
datos_sal= data.frame(Salinidad)

#Breve exploracion de indicadores estadisticos
head(datos_sal)
Biomasa pH Salinidad Zinc Potasio
765.280 5.00 33 16.4524 1441.67
954.017 4.70 35 13.9852 1299.19
827.686 4.20 32 15.3276 1154.27
755.072 4.40 30 17.3128 1045.15
896.176 5.55 33 22.3312 521.62
1422.836 5.50 33 12.2778 1273.02
describe(datos_sal)
vars n mean sd median trimmed mad min max range skew kurtosis se
Biomasa 1 45 1082.172644 546.287433 991.829 1022.020108 526.398613 369.8230 2337.3260 1967.503 0.9062470 -0.0223200 81.4357223
pH 2 45 4.608889 1.254731 4.450 4.456757 1.408470 3.2000 7.4500 4.250 0.8740420 -0.0345939 0.1870443
Salinidad 3 45 30.266667 3.719726 30.000 30.135135 4.447800 24.0000 38.0000 14.000 0.3074678 -1.0359383 0.5545041
Zinc 4 45 17.830796 8.274169 19.242 18.397270 6.618771 0.2105 31.2865 31.076 -0.6635742 -0.0632431 1.2334402
Potasio 5 45 797.377778 297.576022 773.300 778.479730 352.087848 350.7300 1441.6700 1090.940 0.4794017 -1.0027356 44.3600143

A.- Análisis bivariado de correlaciones

Realice un análisis de correlaciones que permita identificar de manera bivariada las relaciones entre las covariables y la respuesta (incluir coeficiente de correlación e interpretaciones).
En este caso se realiza un análisis bivariado recurriendo una matriz de correlaciones para observar con que fuerza se relacionan las distintas variables predictoras frente a la variable respuesta (Biomasa)

De acuerdo con el resultado obtenido, los predictores que mas tienen correlación con la \(Biomasa\) son \(pH\) con un Coeficiente de Correlación \(R=0.928\) (correlación positiva) y \(Zinc\) con un Coeficiente de Correlación \(R=-0.781\) (correlación negativa).

library(GGally)
ggpairs(datos_sal, columns=c("Biomasa", "pH", "Salinidad", "Zinc", "Potasio"), columnLabels = c("Biomasa", "pH", "Salinidad", "Zinc", "Potasio"), lower = list(continuous = "smooth"), diag = list(continuous = "barDiag"), axisLabels = "none")

B.- Estimación del modelo

Estime el modelo de regresión lineal múltiple para explicar la biomasa en función de las covariables e interprete el valor p, los coeficientes de las variables significativas y el coeficiente R2.
A continuación, se plantea el modelo de Regresión Lineal Múltiple incluyendo todos los predictores.
Podemos consigna el establecimiento de Hipótesis del siguiente modo:
Hipótesis Nula: No existe ningún predictor correlacionado con la variable respuesta. \(H0: β1 = … = βp−1=0\)
Hipótesis Alternativa: Existe al menos un predictor correlacionado con la variable respuesta \(H1: βi≠0\)

modelo_s=lm(Biomasa~pH+Salinidad+Zinc+Potasio,data=datos_sal)
summary(modelo_s)
## 
## Call:
## lm(formula = Biomasa ~ pH + Salinidad + Zinc + Potasio, data = datos_sal)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -293.98  -88.83   -9.48   88.20  387.27 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 1492.8076   453.6013   3.291 0.002091 ** 
## pH           262.8829    33.7304   7.794 1.51e-09 ***
## Salinidad    -33.4997     8.6525  -3.872 0.000391 ***
## Zinc         -28.9727     5.6643  -5.115 8.20e-06 ***
## Potasio       -0.1150     0.0819  -1.404 0.167979    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 158.9 on 40 degrees of freedom
## Multiple R-squared:  0.9231, Adjusted R-squared:  0.9154 
## F-statistic:   120 on 4 and 40 DF,  p-value: < 2.2e-16
par(mfrow=c(2,2))
plot(modelo_s)

De acuerdo con el resultado obtenido tenemos un Coeficiente de Determinación alto \(R^2=0.9154\) y un p-valor general que brinda significancia estadística al modelo \(p-value: < 2.2e-16\).
Sin embargo, se observa que la variable \(Potasio\) no tiene mayor peso o significancia en el modelo frente a la variable respuesta. presenta un elevado \(p-valor=0.167979\) , mayor que el nivel \(\alpha=0.05\) convencional.

En cuanto a los supuestos de modelo podemos establecer lo siguiente:
1.- Homocedasticidad: El gráfico de residuos muestra que los residuos no presentan mayor tendencia o sesgo. Podemos decir que la varianza es en general constante. Sin embargo, a continuacion se realiza un test de varianza de Breusch-Pagan [2]. Se plantean las siguientes hipótesis:
\(\text{H0: Los residuos presentan varianza constante.}\)
\(\text{H1: Los residuos no tienen varianza constante.}\)

El resultado con un \(p-valor=0.24\) indica que No se rechaza la Hipotesis Nula \(H0\), y los residuos presentan una variaza constante. Se cumple el supuesto.

library(lmtest)
bptest(modelo_s)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo_s
## BP = 5.4945, df = 4, p-value = 0.2402

2.- Normalidad de los residuos. El gráfico Q-Q de normalidad muestra que los residuos presentan una Distribución Normal. Para verificar esta observación gráfica, a continuación se plantea un test de normalidad de Shapiro-Wilks sobre los residuos. Se plantean las siguientes hipótesis:
\(\text{H0: Los residuos presentan una Distribución Normal}\)
\(\text{H1: Los residuos no presentan una Distribución Normal}\)
El resultado del test con un \(p-valor=0.2036\) indica que No se rechaza la Hipótesis Nula \(H0\), y los residuos presentan una Distribución Normal. Se cumple el supuesto.

residuos_modelo_s <- modelo_s$residuals
shapiro.test(residuos_modelo_s)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuos_modelo_s
## W = 0.96586, p-value = 0.2036

3.- No Colinealidad. De acuerdo con la matriz de correlaciones podemos verificar que entre los predictores \(Zinc\) y \(pH\) existe una correlación alta con un \(R=-0.72\). Sin embargo, puesto que las dos variables presentan alta correlación con la variable repuesta \(Biomasa\) y no es una correlación perfecta de 1, se dejará en el modelo. El supuesto se cumple.

4.- Linealidad: De acuerdo con la matriz de correlaciones podemos verificar que, a excepción del predictor \(Potasio\), existe correlación entre los predictores y la variable respuesta. El supuesto se cumple.

5.- Parsimonia: El modelo presenta un alto Coeficiente de Determinación. Sin embargo, eliminaremos del modelo la variable \(Potasio\) para optimizar el numero predictores sin afectar la predictibilidad del modelo. A continuación se plantea el modelo sin la variable \(Potasio\). En efecto se encuentra que el Coeficiente de Determinación no se afecta y es elevado \(R^2=0.9134\). El supuesto se cumple

modelo_s1=lm(Biomasa~pH+Salinidad+Zinc,data=datos_sal)
summary(modelo_s1)
## 
## Call:
## lm(formula = Biomasa ~ pH + Salinidad + Zinc, data = datos_sal)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -363.42 -107.14    8.51   78.33  398.36 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 1502.349    458.894   3.274  0.00216 ** 
## pH           255.008     33.653   7.578 2.55e-09 ***
## Salinidad    -34.800      8.704  -3.998  0.00026 ***
## Zinc         -30.408      5.637  -5.394 3.13e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 160.8 on 41 degrees of freedom
## Multiple R-squared:  0.9193, Adjusted R-squared:  0.9134 
## F-statistic: 155.7 on 3 and 41 DF,  p-value: < 2.2e-16

Finalmente el modelo de Regresión Lineal Múltiple podemos establecerlo del siguiente modo: \(Y= 1502.34 + 255pH - 34.8Salinidad - 30.408Zinc\)

BIBLIOGRAFIA

[1] Camacho Martinez, C. 2022. “Interaccion en Regresión”. Recurso disponible en: https://personal.us.es/vararey/adatos2/interaccion.pdf. Consultado en septiembre de 2022.
[1]Hernandez, F & Mazo, M. 2020. “Modelos de Regresion con R”. Recurso disponible en: https://fhernanb.github.io/libro_regresion/homo.html. Consultado en septiembre de 2022.