Este informe analiza plazos de ejecución y costos de
instalación de puentes modulares en Perú mediante
modelos de regresión lineal.
Se busca: - Estimar el plazo de ejecución (días) para
nuevos contratos. - Verificar los supuestos de
regresión (linealidad, independencia, homocedasticidad y
normalidad). - Comparar varios modelos y elegir el más adecuado.
library(tidyverse)
library(readxl)
library(car)
library(lmtest)
library(ggpubr)
library(boot)
Se cuenta con 18 puentes concluidos y 9 puentes que se encuentran en ejecucion.
Objetivo: Estimar el plazo de ejecución (dias) en puentes modulares para este primer modelo solo se va a usar los 18 contratos que ya concluyeron, de este modelo estimar el plazo de ejecución de los 9 puentes que se encuentran en ejecucion , durante el periodo 2021-2025
# Lectura del archivo Excel
datos <- read_excel("PUENTES_18.07.2025.xlsx")
# Selección de variables relevantes (primeros 18 contratos concluidos)
datos_modelo <- datos[1:18, c("Dias", "PUENTES", "METROS", "longxp","Ugeog","lluvia")]
# Exploración rápida
head(datos_modelo)
## # A tibble: 6 × 6
## Dias PUENTES METROS longxp Ugeog lluvia
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 273 2 140. 69.8 2 0
## 2 267 2 149. 74.4 2 0
## 3 217 6 152. 25.4 2 0
## 4 183 9 104. 11.5 2 0
## 5 271 1 100. 100. 1 0
## 6 172 1 81 81 2 1
summary(datos_modelo)
## Dias PUENTES METROS longxp
## Min. :172.0 Min. : 1.000 Min. : 54.86 Min. : 11.51
## 1st Qu.:268.0 1st Qu.: 2.000 1st Qu.:106.58 1st Qu.: 20.25
## Median :296.5 Median : 5.000 Median :147.59 Median : 31.40
## Mean :322.2 Mean : 5.056 Mean :158.88 Mean : 48.76
## 3rd Qu.:356.0 3rd Qu.: 7.000 3rd Qu.:161.72 3rd Qu.: 73.29
## Max. :652.0 Max. :12.000 Max. :416.25 Max. :155.45
## Ugeog lluvia
## Min. :1.000 Min. :0.0000
## 1st Qu.:2.000 1st Qu.:0.0000
## Median :2.000 Median :1.0000
## Mean :1.889 Mean :0.5556
## 3rd Qu.:2.000 3rd Qu.:1.0000
## Max. :2.000 Max. :1.0000
Las variables con las que se van a trabajar son: plazo (días), número de puentes, metros totales y longitud promedio por puente (longxp) para 18 contratos con servicios concluidos.
# Gráficos exploratorios
g1 <- ggplot(datos_modelo, aes(PUENTES, Dias)) +
geom_point() + geom_smooth(method = "lm", se = FALSE) +
labs(title = "Plazo vs Número de Puentes")
g2 <- ggplot(datos_modelo, aes(METROS, Dias)) +
geom_point() + geom_smooth(method = "lm", se = FALSE) +
labs(title = "Plazo vs Metros Totales")
g3 <- ggplot(datos_modelo, aes(longxp, Dias)) +
geom_point() + geom_smooth(method = "lm", se = FALSE) +
labs(title = "Plazo vs Longitud por Puente")
ggarrange(g1, g2, g3, ncol = 3)
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
Conclusión: La relación es más clara entre plazo y longitud promedio por puente (longxp), lo que sugiere que este predictor puede ser más útil que los metros totales.
##
## Call:
## lm(formula = Dias ~ longxp + PUENTES + as.factor(Ugeog) + as.factor(lluvia),
## data = datos_modelo2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -155.24 -43.55 17.18 43.55 139.91
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 308.3373 153.1455 2.013 0.0671 .
## longxp -0.8631 1.3566 -0.636 0.5366
## PUENTES 5.5091 10.5031 0.525 0.6095
## as.factor(Ugeog)2 -9.7465 87.5306 -0.111 0.9132
## as.factor(lluvia)1 19.8810 44.7838 0.444 0.6650
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 89.55 on 12 degrees of freedom
## Multiple R-squared: 0.2233, Adjusted R-squared: -0.03557
## F-statistic: 0.8626 on 4 and 12 DF, p-value: 0.5136
##
## Call:
## lm(formula = Dias ~ longxp + PUENTES + as.factor(Ugeog) + as.factor(lluvia) +
## dummy_2364, data = datos_modelo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -155.24 -42.12 8.59 40.90 139.91
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 308.3373 153.1455 2.013 0.0671 .
## longxp -0.8631 1.3566 -0.636 0.5366
## PUENTES 5.5091 10.5031 0.525 0.6095
## as.factor(Ugeog)2 -9.7465 87.5306 -0.111 0.9132
## as.factor(lluvia)1 19.8810 44.7838 0.444 0.6650
## dummy_2364 462.1869 167.7548 2.755 0.0174 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 89.55 on 12 degrees of freedom
## Multiple R-squared: 0.5975, Adjusted R-squared: 0.4298
## F-statistic: 3.563 on 5 and 12 DF, p-value: 0.03311
##
## Call:
## lm(formula = Dias ~ longxp + PUENTES + as.factor(lluvia) + as.factor(dummy_2364),
## data = datos_modelo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -153.86 -37.90 7.98 43.42 140.46
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 295.8312 100.0780 2.956 0.01114 *
## longxp -0.7862 1.1227 -0.700 0.49608
## PUENTES 5.5644 10.0849 0.552 0.59048
## as.factor(lluvia)1 20.5404 42.6710 0.481 0.63826
## as.factor(dummy_2364)1 452.2858 136.7402 3.308 0.00566 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 86.08 on 13 degrees of freedom
## Multiple R-squared: 0.5971, Adjusted R-squared: 0.4731
## F-statistic: 4.817 on 4 and 13 DF, p-value: 0.01325
##
## Call:
## lm(formula = Dias ~ longxp + as.factor(lluvia) + as.factor(dummy_2364),
## data = datos_modelo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -147.096 -46.033 6.356 44.486 142.362
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 344.4254 46.3320 7.434 3.18e-06 ***
## longxp -1.2447 0.7361 -1.691 0.11299
## as.factor(lluvia)1 21.1792 41.5822 0.509 0.61845
## as.factor(dummy_2364)1 479.8797 124.0647 3.868 0.00171 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 83.91 on 14 degrees of freedom
## Multiple R-squared: 0.5877, Adjusted R-squared: 0.4993
## F-statistic: 6.651 on 3 and 14 DF, p-value: 0.005087
##
## Call:
## lm(formula = Dias ~ longxp + as.factor(Ugeog) + as.factor(lluvia),
## data = datos_modelo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -232.59 -56.08 -26.93 82.36 165.55
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 106.473 108.287 0.983 0.342
## longxp 1.204 0.764 1.576 0.137
## as.factor(Ugeog)2 136.655 91.694 1.490 0.158
## as.factor(lluvia)1 63.947 53.247 1.201 0.250
##
## Residual standard error: 112.1 on 14 degrees of freedom
## Multiple R-squared: 0.2638, Adjusted R-squared: 0.1061
## F-statistic: 1.672 on 3 and 14 DF, p-value: 0.2183
Conclusión:
Modelo 6 (Dias ~ longxp + PUENTES+as.factor(Ugeog)+as.factor(lluvia)+dummy_2364): vemos que añadir el valor dummy muestra mejor ajuste y añade mas valor al modelo ya que su presencia hace que el modelo explique de manera mucho mas significativa los datos. Es decir considerar el dummy es importante para representar el comportamiento real de los datos r2=60%
Modelo 7 (Dias ~ longxp + PUENTES+as.factor(lluvia)+as.factor(dummy_2364)):a pesar de haber sacado la variable Ubicación geografica el modelo se sigue manteniendo, lo que nos hace pensar que la variable dummy es la que añade mayor axplicación al modelo r2=60%
Modelo 8 (Dias ~ longxp +as.factor(lluvia)+as.factor(dummy_2364)) Sin ubicación geografica, sin num puentes el modelo reduce su R2 por lo que las variables que se sacaron aportan un 1% del comportamiento de los datos para explicar el modelo, se podrìa decir que el numero de puentes y la ubicación geografica capturan una poca variabilidad de todo el modelo r2=59%
OBSERVACIÓNSe añadieron las variables Ubicación geografica (costa=1,sierra=2,selva=3), y estacion de lluvia (generalmente la temporada se lluvias se distribuye desde los mese de Nov a Mar por ende se ha tomado como lluvia=1, los que se encuentren dentro de este intervalo de meses y no lluvia=0 ,los contratos que no estan dentro de este intervalo)
H0, No hay autocorrelacion en los residuos.
H1, Si hay autorrelación, lo que significaría que no cumple este supuesto.
dwtest(modelo6)
##
## Durbin-Watson test
##
## data: modelo6
## DW = 2.361, p-value = 0.7949
## alternative hypothesis: true autocorrelation is greater than 0
dwtest(modelo7)
##
## Durbin-Watson test
##
## data: modelo7
## DW = 2.3878, p-value = 0.8018
## alternative hypothesis: true autocorrelation is greater than 0
dwtest(modelo8)
##
## Durbin-Watson test
##
## data: modelo8
## DW = 2.4934, p-value = 0.8271
## alternative hypothesis: true autocorrelation is greater than 0
Conclusión: P-valores > 0.05 → Los residuos cumplen con el supuesto de independencia. no hay variables autocorrelacionadas cada variable aporta independientemente
par(mfrow = c(1, 2))
plot(modelo6$fitted.values, resid(modelo6),
main = "Residuos vs Ajustados (Modelo 6)",
xlab = "Valores Ajustados", ylab = "Residuos")
abline(h = 0, col = "red")
plot(modelo7$fitted.values, resid(modelo7),
main = "Residuos vs Ajustados (Modelo 7)",
xlab = "Valores Ajustados", ylab = "Residuos")
abline(h = 0, col = "red")
plot(modelo8$fitted.values, resid(modelo8),
main = "Residuos vs Ajustados (Modelo 8)",
xlab = "Valores Ajustados", ylab = "Residuos")
abline(h = 0, col = "red")
Conclusión: Los residuos están dispersos sin patrón evidente → se cumple
la homocedasticidad.
# Histograma y QQ Plot Modelo 7
hist(resid(modelo7), col = "skyblue", main = "Residuos Modelo 7")
qqnorm(resid(modelo7)); qqline(resid(modelo7), col = "red")
# Prueba de Shapiro-Wilk
shapiro.test(resid(modelo7))
##
## Shapiro-Wilk normality test
##
## data: resid(modelo7)
## W = 0.98422, p-value = 0.983
Conclusión: Si el p-valor > 0.05, los residuos no se alejan significativamente de la normalidad. El modelo 7 cumple mejor este supuesto que los demás.
Modelo 7 (Dias ~ longxp + PUENTES+as.factor(lluvia)+as.factor(dummy_2364)) por ser mas simple es el adecuado.
El Modelo 7 explica la misma variabilidad que la del modelo 6 pero este es mas simple(mayor R²).
Se recomienda utilizar el Modelo 7 para predecir plazos de nuevos contratos.
summary(modelo7)
##
## Call:
## lm(formula = Dias ~ longxp + PUENTES + as.factor(lluvia) + as.factor(dummy_2364),
## data = datos_modelo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -153.86 -37.90 7.98 43.42 140.46
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 295.8312 100.0780 2.956 0.01114 *
## longxp -0.7862 1.1227 -0.700 0.49608
## PUENTES 5.5644 10.0849 0.552 0.59048
## as.factor(lluvia)1 20.5404 42.6710 0.481 0.63826
## as.factor(dummy_2364)1 452.2858 136.7402 3.308 0.00566 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 86.08 on 13 degrees of freedom
## Multiple R-squared: 0.5971, Adjusted R-squared: 0.4731
## F-statistic: 4.817 on 4 and 13 DF, p-value: 0.01325
Con un R2 de 60% el modelo Y=295.8312-0.786x1+5.5644x2+20.5404x3+452.285x4
#datos de contrato en ejecución
#modelo 6 (Dias ~ longxp + PUENTES+as.factor(Ugeog)+as.factor(lluvia)+dummy_2364)
#modelo 7 (Dias ~ longxp + PUENTES+as.factor(lluvia)+as.factor(dummy_2364))
#modelo 8 (Dias ~ longxp +as.factor(lluvia)+as.factor(dummy_2364))
nuevos_datos <- data.frame(
longxp = c(28,37,26,41,40,34,30,48,20),
PUENTES = c(11,10,7,9,7,5,3,5,6),
#Ugeog=c(2,1,2,1,2,2,2,2,1),
lluvia=c(1,1,1,1,1,1,1,1,1),
dummy_2364=c(0,1,0,1,0,0,0,0,0)
#num de PUENTES valores
)
# Estimar el plazo para esos nuevos datos
predicciones <- predict(modelo7, newdata = nuevos_datos, interval = "confidence")
print(predicciones)
## fit lwr upr
## 1 355.5651 239.3391 471.7911
## 2 795.2103 526.5267 1063.8939
## 3 334.8800 269.9097 399.8503
## 4 786.5009 521.1558 1051.8461
## 5 323.8726 254.1806 393.5645
## 6 317.4612 251.1978 383.7247
## 7 309.4774 212.5555 406.3994
## 8 306.4538 241.9987 370.9089
## 9 334.0331 261.0996 406.9665
mean(predicciones[1,])
## [1] 355.5651
Se añadió variables dummy (652 dias el mayor plazo) ya que su comportamiento es anormal en comparación con el resto, no es recomendable quitar de la muestra ya que es importante capturar su influencia en el modelo, por su importancia operativa.
Luego de esto vemos que el modelo es estadisticamente aceptable.
El modelo aumenta su calidad a 60 % una mejora sólida
El modelo es útil como herramienta de estimación.
La inclusión de outliers o casos especiales parece beneficiar la estabilidad del modelo.