# Librerías necesarias
library(readxl)
library(ggplot2)
library(GGally)
library(dplyr)
library(car)
library(lmtest)
library(nortest)
library(corrplot)
library(knitr)
library(kableExtra)El dataset Iris (Fisher, 1936) contiene mediciones morfológicas de 150 flores pertenecientes a tres especies del género Iris: setosa, versicolor y virginica. Cada observación registra cuatro variables continuas (longitud y ancho del sépalo y del pétalo) expresadas en centímetros.
Determinar si existe una relación estadísticamente significativa
entre las dimensiones del pétalo y el sépalo, con el fin de construir
modelos de regresión que permitan predecir la longitud del
sépalo (Sepal.Length) a partir de las demás
variables morfológicas.
Sepal.Length: Longitud del sépalo
(cm)Petal.Length – Longitud del pétalo
(cm)Sepal.Width – Ancho del sépalo (cm)Petal.Width – Ancho del pétalo (cm)\[H_0: \beta_1 = 0 \quad \text{(La longitud del pétalo NO predice la longitud del sépalo)}\] \[H_1: \beta_1 \neq 0 \quad \text{(La longitud del pétalo SÍ predice la longitud del sépalo)}\]
\[H_0: \beta_1 = \beta_2 = \beta_3 = 0 \quad \text{(Ninguna variable predictora explica la longitud del sépalo)}\] \[H_1: \exists\ \beta_j \neq 0 \quad \text{(Al menos una variable predictora es significativa)}\]
Nivel de significancia: \(\alpha = 0.05\)
# Se abre la base de datos de Excel desde la libreria de Rstudio
ruta_archivo <- "ModelodeRegresionModulo.xlsx"
if (!file.exists(ruta_archivo)) {
posibles <- list.files(path = ".", pattern = "ModelodeRegresionModulo",
recursive = TRUE, full.names = TRUE)
if (length(posibles) > 0) ruta_archivo <- posibles[1]
}
datos <- read_excel(ruta_archivo)
# Variables numéricas (se usará en todo el análisis)
datos_num <- datos %>% select(-Species)
# Verificación de estructura
glimpse(datos)## Rows: 150
## Columns: 5
## $ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.…
## $ Sepal.Width <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…
## $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.…
## $ Petal.Width <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
## $ Species <chr> "setosa", "setosa", "setosa", "setosa", "setosa", "setosa…
resumen_tabla <- data.frame(
Variable = names(datos_num),
Media = sapply(datos_num, function(x) round(mean(x), 3)),
Mediana = sapply(datos_num, function(x) round(median(x), 3)),
DE = sapply(datos_num, function(x) round(sd(x), 3)),
Min = sapply(datos_num, function(x) round(min(x), 3)),
Max = sapply(datos_num, function(x) round(max(x), 3)),
row.names = NULL
)
kable(resumen_tabla,
caption = "Tabla 1. Estadísticas descriptivas de las variables numéricas",
booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)| Variable | Media | Mediana | DE | Min | Max |
|---|---|---|---|---|---|
| Sepal.Length | 5.843 | 5.80 | 0.828 | 4.3 | 7.9 |
| Sepal.Width | 3.057 | 3.00 | 0.436 | 2.0 | 4.4 |
| Petal.Length | 3.758 | 4.35 | 1.765 | 1.0 | 6.9 |
| Petal.Width | 1.199 | 1.30 | 0.762 | 0.1 | 2.5 |
Descripción de las variables:
| Variable | Tipo | Descripción | Unidad |
|---|---|---|---|
Sepal.Length |
Continua — Dependiente (Y) | Longitud del sépalo | cm |
Sepal.Width |
Continua — Predictora | Ancho del sépalo | cm |
Petal.Length |
Continua — Predictora principal | Longitud del pétalo | cm |
Petal.Width |
Continua — Predictora | Ancho del pétalo | cm |
Species |
Categórica nominal | Especie de Iris | — |
La variable dependiente Sepal.Length presenta una media
de 5.84 cm con desviación estándar de 0.83
cm, lo que indica una variabilidad moderada en la muestra.
# Matriz de correlación de Pearson
cor_matrix <- cor(datos_num, method = "pearson")
corrplot(cor_matrix,
method = "color",
type = "upper",
addCoef.col = "black",
tl.col = "black",
tl.srt = 45,
col = colorRampPalette(c("#d73027","#f7f7f7","#1a9641"))(200),
title = "Figura 1. Matriz de Correlación de Pearson",
mar = c(0,0,1,0))kable(round(cor_matrix, 4),
caption = "Tabla 2. Coeficientes de correlación de Pearson",
booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE)| Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | |
|---|---|---|---|---|
| Sepal.Length | 1.0000 | -0.1176 | 0.8718 | 0.8179 |
| Sepal.Width | -0.1176 | 1.0000 | -0.4284 | -0.3661 |
| Petal.Length | 0.8718 | -0.4284 | 1.0000 | 0.9629 |
| Petal.Width | 0.8179 | -0.3661 | 0.9629 | 1.0000 |
ggpairs(datos_num,
title = "Figura 2. Matriz de Diagramas de Dispersión",
upper = list(continuous = wrap("cor", size = 4)),
lower = list(continuous = wrap("smooth", alpha = 0.4, color = "#2c7bb6")),
diag = list(continuous = wrap("densityDiag", fill = "#abd9e9"))) +
theme_bw(base_size = 11)Interpretación: Petal.Length presenta
la correlación más alta con Sepal.Length (\(r = 0.8718\)), lo que la convierte en la
candidata natural para el modelo simple.
shapiro_tabla <- data.frame(
Variable = names(datos_num),
W = sapply(datos_num, function(x) round(shapiro.test(x)$statistic, 4)),
p_valor = sapply(datos_num, function(x) round(shapiro.test(x)$p.value, 4)),
Decision = sapply(datos_num, function(x) ifelse(shapiro.test(x)$p.value > 0.05,
"No rechazar H0 (Normal)",
"Rechazar H0 (No normal)")),
row.names = NULL
)
kable(shapiro_tabla,
caption = "Tabla 3. Prueba de normalidad de Shapiro-Wilk (α = 0.05)",
row.names = FALSE,
booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE)| Variable | W | p_valor | Decision |
|---|---|---|---|
| Sepal.Length | 0.9761 | 0.0102 | Rechazar H0 (No normal) |
| Sepal.Width | 0.9849 | 0.1012 | No rechazar H0 (Normal) |
| Petal.Length | 0.8763 | 0.0000 | Rechazar H0 (No normal) |
| Petal.Width | 0.9018 | 0.0000 | Rechazar H0 (No normal) |
par(mfrow = c(2,2))
for(v in names(datos_num)){
qqnorm(datos_num[[v]], main = paste("Q-Q Plot:", v), col = "#2c7bb6", pch = 16)
qqline(datos_num[[v]], col = "#d7191c", lwd = 2)
}Se ajusta el modelo:
\[\widehat{Sepal.Length}_i = \beta_0 + \beta_1 \cdot Petal.Length_i + \varepsilon_i\]
##
## Call:
## lm(formula = Sepal.Length ~ Petal.Length, data = datos)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.24675 -0.29657 -0.01515 0.27676 1.00269
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.30660 0.07839 54.94 <2e-16 ***
## Petal.Length 0.40892 0.01889 21.65 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4071 on 148 degrees of freedom
## Multiple R-squared: 0.76, Adjusted R-squared: 0.7583
## F-statistic: 468.6 on 1 and 148 DF, p-value: < 2.2e-16
coef_df <- as.data.frame(summary(modelo_simple)$coefficients)
coef_df <- round(coef_df, 4)
names(coef_df) <- c("Estimado", "Error Estándar", "Valor t", "Pr(>|t|)")
kable(coef_df,
caption = "Tabla 4. Coeficientes del modelo de regresión simple",
booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE)| Estimado | Error Estándar | Valor t | Pr(>|t|) | |
|---|---|---|---|---|
| (Intercept) | 4.3066 | 0.0784 | 54.9389 | 0 |
| Petal.Length | 0.4089 | 0.0189 | 21.6460 | 0 |
La ecuación ajustada es:
\[\widehat{Sepal.Length} = 4.3066 + 0.4089 \cdot Petal.Length\]
ggplot(datos, aes(x = Petal.Length, y = Sepal.Length)) +
geom_point(aes(color = Species), alpha = 0.7, size = 2.5) +
geom_smooth(method = "lm", se = TRUE, color = "#d7191c", linewidth = 1.2) +
labs(title = "Figura 3. Regresión Lineal Simple: Sepal.Length ~ Petal.Length",
x = "Longitud del Pétalo (cm)",
y = "Longitud del Sépalo (cm)") +
theme_bw(base_size = 12) +
scale_color_brewer(palette = "Set1")Interpretación de coeficientes:
Petal.Length, la longitud del sépalo
aumenta en promedio 0.4089 cm.Sepal.Length.# Gráfico residuos vs valores ajustados
ggplot(data.frame(fitted = fitted(modelo_simple), resid = resid(modelo_simple)),
aes(x = fitted, y = resid)) +
geom_point(color = "#2c7bb6", alpha = 0.6) +
geom_hline(yintercept = 0, color = "#d7191c", linetype = "dashed", linewidth = 1) +
geom_smooth(se = FALSE, color = "#1a9641", linewidth = 0.8) +
labs(title = "Figura 4. Residuos vs Valores Ajustados (Linealidad)",
x = "Valores Ajustados", y = "Residuos") +
theme_bw()dw_test <- dwtest(modelo_simple)
cat("Durbin-Watson:", round(dw_test$statistic, 4),
"\np-valor:", round(dw_test$p.value, 4))## Durbin-Watson: 1.8673
## p-valor: 0.1852
Un estadístico D-W cercano a 2 indica ausencia de autocorrelación. Si \(p > 0.05\), no se rechaza la hipótesis de independencia.
bp_test <- bptest(modelo_simple)
cat("Breusch-Pagan χ²:", round(bp_test$statistic, 4),
"\np-valor:", round(bp_test$p.value, 4))## Breusch-Pagan χ²: 2.7561
## p-valor: 0.0969
Si \(p > 0.05\) → varianza constante (homocedasticidad).
## Media de residuos: 0
Por construcción matemática del método de MCO, la media de los residuos es siempre igual a 0.
sw_res <- shapiro.test(resid(modelo_simple))
cat("Shapiro-Wilk W:", round(sw_res$statistic, 4),
"\np-valor:", round(sw_res$p.value, 4))## Shapiro-Wilk W: 0.993
## p-valor: 0.6767
# Histograma de residuos
ggplot(data.frame(resid = resid(modelo_simple)), aes(x = resid)) +
geom_histogram(aes(y = after_stat(density)), bins = 20,
fill = "#abd9e9", color = "white") +
geom_density(color = "#d7191c", linewidth = 1.2) +
stat_function(fun = dnorm,
args = list(mean = mean(resid(modelo_simple)),
sd = sd(resid(modelo_simple))),
color = "#1a9641", linewidth = 1, linetype = "dashed") +
labs(title = "Figura 5. Distribución de Residuos (Modelo Simple)",
x = "Residuos", y = "Densidad") +
theme_bw()kable(data.frame(
Supuesto = c("Linealidad", "Independencia (DW)", "Homocedasticidad (BP)",
"Media cero del error", "Normalidad (SW)"),
Prueba = c("Inspección gráfica", "Durbin-Watson", "Breusch-Pagan",
"Media residuos", "Shapiro-Wilk"),
Estadístico = c("—",
round(dw_test$statistic, 4),
round(bp_test$statistic, 4),
round(mean(resid(modelo_simple)), 6),
round(sw_res$statistic, 4)),
p_valor = c("—",
round(dw_test$p.value, 4),
round(bp_test$p.value, 4),
"—",
round(sw_res$p.value, 4)),
Conclusion = c("Relación aproximadamente lineal",
ifelse(dw_test$p.value > 0.05, "✅ Se cumple", "⚠️ Posible violación"),
ifelse(bp_test$p.value > 0.05, "✅ Se cumple", "⚠️ Posible violación"),
"✅ Se cumple (por MCO)",
ifelse(sw_res$p.value > 0.05, "✅ Se cumple", "⚠️ Posible violación"))
),
caption = "Tabla 5. Evaluación de supuestos de Gauss-Markov — Modelo Simple",
row.names = FALSE, booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE)| Supuesto | Prueba | Estadístico | p_valor | Conclusion |
|---|---|---|---|---|
| Linealidad | Inspección gráfica | — | — | Relación aproximadamente lineal |
| Independencia (DW) | Durbin-Watson | 1.8673 | 0.1852 | ✅ Se cumple | |
| Homocedasticidad (BP) | Breusch-Pagan | 2.7561 | 0.0969 | ✅ Se cumple | |
| Media cero del error | Media residuos | 0 | — | ✅ Se cumple (por MCO) | |
| Normalidad (SW) | Shapiro-Wilk | 0.993 | 0.6767 | ✅ Se cumple | |
\[\widehat{Sepal.Length}_i = \beta_0 + \beta_1 \cdot Petal.Length_i + \beta_2 \cdot Sepal.Width_i + \beta_3 \cdot Petal.Width_i + \varepsilon_i\]
modelo_multiple <- lm(Sepal.Length ~ Petal.Length + Sepal.Width + Petal.Width,
data = datos)
summary(modelo_multiple)##
## Call:
## lm(formula = Sepal.Length ~ Petal.Length + Sepal.Width + Petal.Width,
## data = datos)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.82816 -0.21989 0.01875 0.19709 0.84570
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.85600 0.25078 7.401 9.85e-12 ***
## Petal.Length 0.70913 0.05672 12.502 < 2e-16 ***
## Sepal.Width 0.65084 0.06665 9.765 < 2e-16 ***
## Petal.Width -0.55648 0.12755 -4.363 2.41e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3145 on 146 degrees of freedom
## Multiple R-squared: 0.8586, Adjusted R-squared: 0.8557
## F-statistic: 295.5 on 3 and 146 DF, p-value: < 2.2e-16
coef_m <- as.data.frame(summary(modelo_multiple)$coefficients)
coef_m <- round(coef_m, 4)
names(coef_m) <- c("Estimado", "Error Estándar", "Valor t", "Pr(>|t|)")
kable(coef_m,
caption = "Tabla 6. Coeficientes del modelo de regresión múltiple",
booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE) %>%
row_spec(which(coef_m[["Pr(>|t|)"]] < 0.05), background = "#d4edda")| Estimado | Error Estándar | Valor t | Pr(>|t|) | |
|---|---|---|---|---|
| (Intercept) | 1.8560 | 0.2508 | 7.4010 | 0 |
| Petal.Length | 0.7091 | 0.0567 | 12.5025 | 0 |
| Sepal.Width | 0.6508 | 0.0666 | 9.7654 | 0 |
| Petal.Width | -0.5565 | 0.1275 | -4.3629 | 0 |
La ecuación ajustada es:
\[\widehat{Sepal.Length} = 1.856 + 0.7091 \cdot PetalLength + 0.6508 \cdot SepalWidth + (-0.5565) \cdot PetalWidth\]
# Factor de Inflación de Varianza (multicolinealidad)
vif_vals <- vif(modelo_multiple)
kable(data.frame(
Variable = names(vif_vals),
VIF = round(vif_vals, 4),
Diagnostico = ifelse(vif_vals < 5, "✅ Sin multicolinealidad",
ifelse(vif_vals < 10, "⚠️ Multicolinealidad moderada",
"❌ Multicolinealidad alta"))
),
caption = "Tabla 7. Factor de Inflación de la Varianza (VIF)",
row.names = FALSE, booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE)| Variable | VIF | Diagnostico |
|---|---|---|
| Petal.Length | 15.0976 | ❌ Multicolinealidad alta | |
| Sepal.Width | 1.2708 | ✅ Sin multicolinealidad | |
| Petal.Width | 14.2343 | ❌ Multicolinealidad alta | |
# Gráficos de regresión parcial
avPlots(modelo_multiple,
main = "Figura 6. Gráficos de Regresión Parcial",
col = "#2c7bb6", pch = 16)Significancia de predictores:
| Predictor | \(\hat{\beta}\) | p-valor | Significativo |
|---|---|---|---|
Petal.Length |
0.7091 | 0 | ✅ Sí |
Sepal.Width |
0.6508 | 0 | ✅ Sí |
Petal.Width |
-0.5565 | 0 | ✅ Sí |
ggplot(data.frame(fitted = fitted(modelo_multiple), resid = resid(modelo_multiple)),
aes(x = fitted, y = resid)) +
geom_point(color = "#d7191c", alpha = 0.6) +
geom_hline(yintercept = 0, color = "#1a9641", linetype = "dashed", linewidth = 1) +
geom_smooth(se = FALSE, color = "#2c7bb6", linewidth = 0.8) +
labs(title = "Figura 7. Residuos vs Valores Ajustados (Modelo Múltiple)",
x = "Valores Ajustados", y = "Residuos") +
theme_bw()dw_m <- dwtest(modelo_multiple)
cat("Durbin-Watson:", round(dw_m$statistic, 4),
"\np-valor:", round(dw_m$p.value, 4))## Durbin-Watson: 2.0604
## p-valor: 0.6013
bp_m <- bptest(modelo_multiple)
cat("Breusch-Pagan χ²:", round(bp_m$statistic, 4),
"\np-valor:", round(bp_m$p.value, 4))## Breusch-Pagan χ²: 6.9605
## p-valor: 0.0732
## Media de residuos: 0
sw_m <- shapiro.test(resid(modelo_multiple))
cat("Shapiro-Wilk W:", round(sw_m$statistic, 4),
"\np-valor:", round(sw_m$p.value, 4))## Shapiro-Wilk W: 0.9956
## p-valor: 0.9349
ggplot(data.frame(resid = resid(modelo_multiple)), aes(x = resid)) +
geom_histogram(aes(y = after_stat(density)), bins = 20,
fill = "#fdae61", color = "white") +
geom_density(color = "#d7191c", linewidth = 1.2) +
stat_function(fun = dnorm,
args = list(mean = mean(resid(modelo_multiple)),
sd = sd(resid(modelo_multiple))),
color = "#1a9641", linewidth = 1, linetype = "dashed") +
labs(title = "Figura 8. Distribución de Residuos (Modelo Múltiple)",
x = "Residuos", y = "Densidad") +
theme_bw()kable(data.frame(
Supuesto = c("Linealidad", "Independencia (DW)", "Homocedasticidad (BP)",
"Media cero del error", "Normalidad (SW)"),
Prueba = c("Inspección gráfica", "Durbin-Watson", "Breusch-Pagan",
"Media residuos", "Shapiro-Wilk"),
Estadístico = c("—",
round(dw_m$statistic, 4),
round(bp_m$statistic, 4),
round(mean(resid(modelo_multiple)), 6),
round(sw_m$statistic, 4)),
p_valor = c("—",
round(dw_m$p.value, 4),
round(bp_m$p.value, 4),
"—",
round(sw_m$p.value, 4)),
Conclusion = c("Estructura residual aproximada",
ifelse(dw_m$p.value > 0.05, "✅ Se cumple", "⚠️ Posible violación"),
ifelse(bp_m$p.value > 0.05, "✅ Se cumple", "⚠️ Posible violación"),
"✅ Se cumple (por MCO)",
ifelse(sw_m$p.value > 0.05, "✅ Se cumple", "⚠️ Posible violación"))
),
caption = "Tabla 8. Evaluación de supuestos de Gauss-Markov — Modelo Múltiple",
row.names = FALSE, booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE)| Supuesto | Prueba | Estadístico | p_valor | Conclusion |
|---|---|---|---|---|
| Linealidad | Inspección gráfica | — | — | Estructura residual aproximada |
| Independencia (DW) | Durbin-Watson | 2.0604 | 0.6013 | ✅ Se cumple | |
| Homocedasticidad (BP) | Breusch-Pagan | 6.9605 | 0.0732 | ✅ Se cumple | |
| Media cero del error | Media residuos | 0 | — | ✅ Se cumple (por MCO) | |
| Normalidad (SW) | Shapiro-Wilk | 0.9956 | 0.9349 | ✅ Se cumple | |
El Criterio de Información de Akaike (AIC) penaliza la complejidad del modelo:
\[\text{AIC} = 2k - 2\ln(\hat{L})\]
donde \(k\) es el número de parámetros y \(\hat{L}\) es la verosimilitud maximizada. El modelo con menor AIC es preferible.
# Modelo nulo
modelo_nulo <- lm(Sepal.Length ~ 1, data = datos)
# Comparación AIC
aic_tabla <- data.frame(
Modelo = c("Nulo (solo intercepto)",
"Simple (Petal.Length)",
"Múltiple (Petal.Length + Sepal.Width + Petal.Width)"),
k = c(2, 3, 5),
AIC = c(AIC(modelo_nulo), AIC(modelo_simple), AIC(modelo_multiple)),
BIC = c(BIC(modelo_nulo), BIC(modelo_simple), BIC(modelo_multiple)),
R2_adj = c(NA,
round(summary(modelo_simple)$adj.r.squared, 4),
round(summary(modelo_multiple)$adj.r.squared, 4)),
RMSE = c(round(sqrt(mean(resid(modelo_nulo)^2)), 4),
round(sqrt(mean(resid(modelo_simple)^2)), 4),
round(sqrt(mean(resid(modelo_multiple)^2)), 4))
)
aic_tabla$AIC <- round(aic_tabla$AIC, 2)
aic_tabla$BIC <- round(aic_tabla$BIC, 2)
kable(aic_tabla,
caption = "Tabla 9. Comparación de modelos: AIC, BIC, R² ajustado y RMSE",
row.names = FALSE, booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE) %>%
row_spec(which.min(aic_tabla$AIC), background = "#d4edda", bold = TRUE)| Modelo | k | AIC | BIC | R2_adj | RMSE |
|---|---|---|---|---|---|
| Nulo (solo intercepto) | 2 | 372.08 | 378.10 | NA | 0.8253 |
| Simple (Petal.Length) | 3 | 160.04 | 169.07 | 0.7583 | 0.4044 |
| Múltiple (Petal.Length + Sepal.Width + Petal.Width) | 5 | 84.64 | 99.70 | 0.8557 | 0.3103 |
# Gráfico comparativo de AIC
ggplot(aic_tabla, aes(x = reorder(Modelo, AIC), y = AIC, fill = Modelo)) +
geom_col(width = 0.6, show.legend = FALSE) +
geom_text(aes(label = round(AIC, 1)), vjust = -0.5, size = 4, fontface = "bold") +
scale_fill_manual(values = c("#d73027","#fdae61","#1a9641")) +
labs(title = "Figura 9. Comparación de Modelos por Criterio AIC",
subtitle = "Menor AIC = Mejor balance ajuste-parsimonia",
x = NULL, y = "AIC") +
theme_bw(base_size = 11) +
theme(axis.text.x = element_text(angle = 15, hjust = 1))# Delta AIC
aic_vals <- c(AIC(modelo_nulo), AIC(modelo_simple), AIC(modelo_multiple))
delta_aic <- aic_vals - min(aic_vals)
w_aic <- exp(-0.5 * delta_aic) / sum(exp(-0.5 * delta_aic))
kable(data.frame(
Modelo = aic_tabla$Modelo,
AIC = round(aic_vals, 2),
ΔAIC = round(delta_aic, 2),
Peso_AIC = round(w_aic, 4),
Soporte = ifelse(delta_aic <= 2, "Fuerte soporte",
ifelse(delta_aic <= 7, "Soporte moderado", "Sin soporte"))
),
caption = "Tabla 10. Delta AIC y pesos de evidencia de Akaike",
row.names = FALSE, booktabs = TRUE) %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE) %>%
row_spec(which.min(aic_vals), background = "#d4edda", bold = TRUE)| Modelo | AIC | ΔAIC | Peso_AIC | Soporte |
|---|---|---|---|---|
| Nulo (solo intercepto) | 372.08 | 287.44 | 0 | Sin soporte |
| Simple (Petal.Length) | 160.04 | 75.40 | 0 | Sin soporte |
| Múltiple (Petal.Length + Sepal.Width + Petal.Width) | 84.64 | 0.00 | 1 | Fuerte soporte |
mejor_modelo <- if(AIC(modelo_multiple) < AIC(modelo_simple)) modelo_multiple else modelo_simple
cat("=== MODELO SELECCIONADO ===\n")## === MODELO SELECCIONADO ===
## AIC Modelo Simple: 160.04
## AIC Modelo Múltiple: 84.64
cat("\nModelo ganador: Regresión Lineal",
ifelse(AIC(modelo_multiple) < AIC(modelo_simple), "MÚLTIPLE", "SIMPLE"), "\n")##
## Modelo ganador: Regresión Lineal MÚLTIPLE
Correlación: Petal.Length es el
predictor más fuertemente correlacionado con Sepal.Length
(\(r = 0.872\)), seguido de
Petal.Width (\(r =
0.818\)). Sepal.Width muestra correlación negativa
débil (\(r = -0.118\)).
Modelo Simple: El modelo
Sepal.Length ~ Petal.Length explica aproximadamente el
76% de la variabilidad (\(R^2
= 0.76\)), con la pendiente altamente significativa (\(p < 0.001\)).
Modelo Múltiple: Al incorporar
Sepal.Width y Petal.Width, el \(R^2\) ajustado mejora a
0.8557, con un Error Cuadrático Medio más bajo. Las
tres variables resultaron significativas (\(p
< 0.05\)). No se evidenció multicolinealidad crítica.
Supuestos de Gauss-Markov: Ambos modelos presentan la media de cero del error (propiedad Media cero del error). La normalidad de los residuos y la homocedasticidad deben verificarse con los resultados de las pruebas formales obtenidos al compilar el documento.
Selección AIC: El modelo de regresión
lineal múltiple obtiene el menor AIC y mayor peso de evidencia,
lo que indica que incorporar las tres variables predictoras ofrece el
mejor balance entre ajuste y parsimonia. Se recomienda como modelo final
para la predicción de Sepal.Length.
Análisis realizado con R 4.5.2 — Dataset Iris (Fisher, 1936)