1. Introducción

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.


2. Librerías y Configuración

library(tidyverse)
library(readxl)
library(car)
library(lmtest)
library(ggpubr)
library(boot)

3. Carga y Exploración de datos

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.

4. Análisis de Supuestos de Regresión

4.1. Relación Lineal

# 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.

4.2. Modelos de Regresión Propuestos

## 
## 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)

4.3. Independencia de Errores

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

4.4. Homocedasticidad

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.

4.5. Normalidad de Residuos

# 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.

5. Resultados y Conclusiones Generales

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

6. Estimación de plazos

#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.