library(readr)
library(ggplot2)
library(reshape2)
library(GGally)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(car)
## Loading required package: carData
## 
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
## 
##     recode
library(patchwork)
library(broom)

1. Análisis descriptivo de los datos

En este trabajo se estudia la relación entre la resistencia a la compresión del concreto y la composición de la mezcla, así como la edad de curado. La base de datos contiene distintas mezclas de concreto con sus proporciones (en kg por m³) y la resistencia medida (en MPa).

El objetivo general es construir y analizar un modelo de regresión lineal múltiple que permita explicar y predecir la resistencia a la compresión (csMPa) a partir de los componentes del concreto y su edad (age).

1.1 Descripción de las variables

A continuación se resumen las variables utilizadas en el análisis.

Variables de Entrada (Features)

Estas son las variables cuantitativas predictoras (covariables) utilizadas en el modelo.

Descriptive Name DataFrame Name Unit / Description
Cement (component 1) cement kg in a 1 m³ mixture
Blast Furnace Slag (component 2) slag kg in a 1 m³ mixture
Fly Ash (component 3) flyash kg in a 1 m³ mixture
Water (component 4) water kg in a 1 m³ mixture
Superplasticizer (component 5) superplasticizer kg in a 1 m³ mixture
Coarse Aggregate (component 6) coarseaggregate kg in a 1 m³ mixture
Fine Aggregate (component 7) fineaggregate kg in a 1 m³ mixture
Age age Days (1–365)

Estas covariables resumen la composición física de la mezcla y el tiempo de curado, ambos factores clave para la resistencia final del concreto.

Variable de Salida (Target)

Esta es la variable cuantitativa de respuesta que se desea explicar y predecir.

Descriptive Name DataFrame Name Unit / Description
Concrete compressive strength csMPa MPa (Megapascals)

csMPa representa la resistencia a la compresión del concreto medida en megapascales, que es el principal indicador de calidad estructural de la mezcla.

1.2 Hipótesis a probar

El interés principal es evaluar si los componentes del concreto y su tiempo de curado (edad) tienen una relación estadísticamente significativa con la resistencia a la compresión.

A nivel formal, consideramos el modelo lineal múltiple:

\[ csMPa_{i} = \beta_{0} + \beta_{1} \text{cement}_{i} + \beta_{2} \text{slag}_{i} + \cdots + \beta_{p} X_{pi} + \epsilon_{i} \]

donde \(\epsilon_{i} \sim N(0, \sigma^2)\) independientes.

Hipótesis global del modelo:

\[ H_{0}: \beta_{1} = \beta_{2} = \cdots = \beta_{p} = 0 \text{ (las covariables no explican la resistencia)} \] \[ H_{1}: \exists j \text{ tal que } \beta_{j} \neq 0 \text{ (al menos una covariable tiene efecto)} \]

Hipótesis individuales (por covariable \(X_{j}\)):

\[ H_{0}: \beta_{j} = 0 \text{ (no hay asociación lineal con csMPa)} \] \[ H_{1}: \beta_{j} \neq 0 \text{ (sí hay asociación lineal con csMPa)} \]

En particular, nos interesa comprobar si:

  • Las cantidades de cemento, escoria, ceniza volante, agua, agregados y superplastificante tienen efecto sobre la resistencia.
  • La edad (o funciones de la edad, como log_age) mejora la explicación de la resistencia. ## 1.3 Carga de datos y transformación inicial
df = read_csv("/Users/usermac/Documents/especializacion/metodos de regresion/trabajo2/Concrete_Data_Yeh.csv")
## Rows: 1030 Columns: 9
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (9): cement, slag, flyash, water, superplasticizer, coarseaggregate, fin...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Se crea además la transformación logarítmica de la edad y de la resistencia, ya que es común que la relación con la edad sea aproximadamente logarítmica y que la respuesta presente asimetría:

df$log_age = log(df$age)
df$log_csmpa = log(df$csMPa)

1.4 Distribuciones marginales

Primero, se explora la distribución de la resistencia y de algunos componentes

ggplot(df, aes(x = csMPa)) +
geom_density() +
labs(title = "Gráfico de Densidad csMPa",
x = "csMPa",
y = "Densidad")

Este gráfico permite visualizar si csMPa es aproximadamente simétrica o presenta sesgo (por ejemplo, hacia la derecha), lo que justifica el uso del logaritmo.

ggplot(df, aes(x = cement)) +
geom_density() +
labs(title = "Gráfico de Densidad cement",
x = "cement",
y = "Densidad")

De forma similar, se puede observar la distribución de cement, identificando rangos típicos de contenido de cemento en la mezcla.

Para tener una idea general del tamaño de la base, de los rangos de valores y de posibles valores perdidos (NA), se imprimen los datos y se revisan los NA:

1.5 Exploratory Data Analysis (EDA)

En esta sección se estudian las relaciones bivariadas entre csMPa (y su logaritmo) y las diferentes covariables. Esto permite detectar patrones de linealidad, posibles outliers y motivar transformaciones.

1.5.1 Cemento y resistencia

p1 <- ggplot(data=df, aes(x=cement, y = csMPa)) +
geom_point(alpha = 0.7, size=2, colour = "darkgreen") +
labs(
title = "Cement vs csMPa",
x = "cement (kg/m^3)",
y = "cMPa"
) +
theme_minimal()

p2 <- ggplot(data=df, aes(x=cement, y = log(csMPa))) +
geom_point(alpha = 0.7, size=2, colour = "darkblue") +
labs(
title = "Cement vs log(csMPa)",
x = "cement (kg/m^3)",
y = "log(cMPa)"
) +
theme_minimal()

p1 + p2

En general se espera una relación positiva: a mayor contenido de cemento, mayor resistencia. El gráfico con log(csMPa) ayuda a ver si la relación se vuelve más cercana a lineal.

1.5.2 Slag y resistencia

p1 <- ggplot(data=df, aes(x=slag, y = csMPa)) +
geom_point(alpha = 0.7, size=2, colour = "darkgreen") +
labs(
title = "slag vs csMPa",
x = "slag (kg/m^3)",
y = "cMPa"
) +
theme_minimal()

p2 <- ggplot(data=df, aes(x=slag, y = log(csMPa))) +
geom_point(alpha = 0.7, size=2, colour = "darkblue") +
labs(
title = "slag vs log(csMPa)",
x = "slag (kg/m^3)",
y = "log(cMPa)"
) +
theme_minimal()

p1 + p2

La escoria granulada (slag) puede contribuir a la resistencia especialmente en edades mayores. El gráfico permite ver si el efecto es lineal o si hay niveles a partir de los cuales la ganancia de resistencia se estabiliza.

1.5.3 Agua y resistencia

p1 <- ggplot(data=df, aes(x=water, y = csMPa)) +
geom_point(alpha = 0.7, size=2, colour = "darkgreen") +
labs(
title = "water vs csMPa",
x = "water (kg/m^3)",
y = "cMPa"
) +
theme_minimal()

p2 <- ggplot(data=df, aes(x=water, y = log(csMPa))) +
geom_point(alpha = 0.7, size=2, colour = "darkblue") +
labs(
title = "water vs log(csMPa)",
x = "water (kg/m^3)",
y = "log(cMPa)"
) +
theme_minimal()

p1 + p2

Típicamente se espera que un mayor contenido de agua reduzca la resistencia (relación negativa), debido a relaciones agua/cemento más altas.

1.5.4 Superplasticizer y resistencia

p1 <- ggplot(data=df, aes(x=superplasticizer, y = csMPa))+
geom_point(alpha = 0.7, size=2, colour = "darkgreen")+
labs(
title = "Superplasticizer vs csMPa",
x = "Superplasticizer (kg/m^3)",
y = "cMPa"
) +
theme_minimal()

p2 <- ggplot(data=df, aes(x=superplasticizer, y = log_csmpa))+
geom_point(alpha = 0.7, size=2, colour = "darkblue")+
labs(
title = "Superplasticizer vs Log_csMPa",
x = "Superplasticizer (kg/m^3)",
y = "cMPa"
) +
theme_minimal()
p1+p2

El superplastificante permite reducir agua manteniendo trabajabilidad, por lo que su efecto puede ser indirectamente positivo sobre la resistencia.

1.5.5 Agregados gruesos y finos

p1 <- ggplot(data=df, aes(x=coarseaggregate, y = csMPa))+
geom_point(alpha = 0.7, size=2, colour = "darkgreen")+
labs(
title = "Coarse Aggregate vs csMPa",
x = "Coarse Aggregate (kg/m^3)",
y = "cMPa"
) +
theme_minimal()

p2 <- ggplot(data=df, aes(x=coarseaggregate, y = log_csmpa))+
geom_point(alpha = 0.7, size=2, colour = "darkblue")+
labs(
title = "Coarse Aggregate vs log_csmpa",
x = "Coarse Aggregate (kg/m^3)",
y = "cMPa"
) +
theme_minimal()
p1 + p2

p1 <- ggplot(data=df, aes(x=fineaggregate, y = csMPa))+
geom_point(alpha = 0.7, size=2, colour = "darkgreen")+
labs(
title = "Fine Aggregate vs csMPa",
x = "Fine Aggregate (kg/m^3)",
y = "cMPa"
) +
theme_minimal()

p2 <- ggplot(data=df, aes(x=fineaggregate, y = log_csmpa))+
geom_point(alpha = 0.7, size=2, colour = "darkblue")+
labs(
title = "Fine Aggregate vs log_csmpa",
x = "Fine Aggregate (kg/m^3)",
y = "cMPa"
) +
theme_minimal()
p1 + p2

Los agregados suelen tener un efecto más sutil sobre la resistencia que el cemento o el agua; estas gráficas ayudan a detectar si hay relación clara o si su efecto es más débil.

1.5.6 Edad y transformaciones

p1 <- ggplot(data=df, aes(x=age, y = csMPa))+
geom_point(alpha = 0.7, size=2, colour = "darkgreen")+
labs(
title = "Age vs csMPa",
x = "Age (kg/m^3)",
y = "cMPa"
)

p2 <- ggplot(data=df, aes(x=age, y = log_csmpa))+
geom_point(alpha = 0.7, size=2, colour = "darkblue")+
labs(
title = "Age vs log_csmpa",
x = "Age (kg/m^3)",
y = "log_csmpa"
)

p3 <- ggplot(data=df, aes(x=log_age, y = csMPa))+
geom_point(alpha = 0.7, size=2, colour = "darkred")+
labs(
title = "log_age vs csMPa",
x = "log_age",
y = "cMPa"
)

p4 <- ggplot(data=df, aes(x=log_age, y = log_csmpa))+
geom_point(alpha = 0.7, size=2, colour = "darkorange")+
labs(
title = "log_age vs log_csmpa",
x = "log_age",
y = "log_csmpa"
)
(p1 + p2) / (p3 + p4)

Es común que la resistencia aumente rápidamente al inicio y luego se estabilice, lo que hace que log_age sea una transformación razonable para aproximar una relación más lineal con csMPa o log_csmpa. ## 1.6 Matriz de correlación y asociación entre variables.

cormat = round(cor(df),2)
cormat[upper.tri(cormat)] <- NA
head(cormat)
##                  cement  slag flyash water superplasticizer coarseaggregate
## cement             1.00    NA     NA    NA               NA              NA
## slag              -0.28  1.00     NA    NA               NA              NA
## flyash            -0.40 -0.32   1.00    NA               NA              NA
## water             -0.08  0.11  -0.26  1.00               NA              NA
## superplasticizer   0.09  0.04   0.38 -0.66             1.00              NA
## coarseaggregate   -0.11 -0.28  -0.01 -0.18            -0.27               1
##                  fineaggregate age csMPa log_age log_csmpa
## cement                      NA  NA    NA      NA        NA
## slag                        NA  NA    NA      NA        NA
## flyash                      NA  NA    NA      NA        NA
## water                       NA  NA    NA      NA        NA
## superplasticizer            NA  NA    NA      NA        NA
## coarseaggregate             NA  NA    NA      NA        NA
melted_cormat = melt(cormat, na.rm = TRUE)
head(melted_cormat)
##               Var1   Var2 value
## 1           cement cement  1.00
## 2             slag cement -0.28
## 3           flyash cement -0.40
## 4            water cement -0.08
## 5 superplasticizer cement  0.09
## 6  coarseaggregate cement -0.11
ggplot(data=melted_cormat, aes(x=Var1, y=Var2, fill=value))+
geom_tile(color = "white") +
scale_fill_gradient2(
low="blue", high = "red", mid = "white",
midpoint = 0,
limit = c(-1, 1),
name = "correlación"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, vjust=1, hjust=1, size=10),
axis.text.y = element_text(size=10),
axis.title = element_blank()
) +
geom_text(aes(label=value), color="black", size=3) +
coord_fixed()

La matriz de correlación permite identificar:

Correlaciones fuertes entre csMPa y algunas covariables (por ejemplo, cemento y edad).

Correlaciones altas entre covariables, lo que puede indicar multicolinealidad (importante para la interpretación de los coeficientes y el VIF más adelante).

También se exploran relaciones más detalladas con ggpairs:

ggpairs(df, columns = c("log_csmpa", "cement", "water", "log_age", "slag"))

Este gráfico resume dispersión, correlaciones y distribuciones univariadas de las variables seleccionadas.

1.7 Construcción de variables categóricas para explorar interacciones

cuartiles_log_age = quantile(
df$log_age,
probs = c(0, 0.25, 0.5, 0.75, 1),
na.rm = TRUE
)
mediana_slag = quantile(
df$slag,
probs = c(0, 0.5, 1),
na.rm = TRUE
)
cuartiles_water = quantile(
df$water,
probs = c(0, 0.25, 0.5, 0.75, 1),
na.rm = TRUE
)
df = df %>%
mutate(
categoria_log_edad = cut(
log_age,
breaks = cuartiles_log_age,
labels = c("Q1 (0-25%)", "Q2 (25-50%)", "Q3(50-75%)", "Q4 (75-100)%"),
include.lowest = TRUE
)
)
df = df %>%
mutate(
categoria_slag = cut(
slag,
breaks = mediana_slag,
labels = c("lower_median","upper_median"),
include.lowest = TRUE
)
)
df = df %>%
mutate(
categoria_water = cut(
water,
breaks = cuartiles_water,
labels = c("Q1 (0-25%)", "Q2 (25-50%)", "Q3(50-75%)", "Q4 (75-100)%"),
include.lowest = TRUE
)
)

1.7.1 Gráficos de interacción

ggplot(
df,
aes(x = cement, y=csMPa, color = categoria_log_edad)
) +
geom_point(alpha=0.3) +
geom_smooth(method = "lm", se=FALSE) +
labs(
title = "Interacción entre cement y cuartiles de edad",
x = "cemento",
y = "resistencia concreto",
color = "Cuartil edad"
) +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

ggplot(
df,
aes(x = water, y=csMPa, color = categoria_log_edad)
) +
geom_point(alpha=0.3) +
geom_smooth(method = "lm", se=FALSE) +
labs(
title = "Interacción entre water y cuartiles de edad",
x = "water",
y = "resistencia concreto",
color = "Cuartil edad"
) +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

ggplot(
df,
aes(x = cement, y=csMPa, color = categoria_slag)
) +
geom_point(alpha=0.3) +
geom_smooth(method = "lm", se=FALSE) +
labs(
title = "Interacción entre cement y categorías de slag",
x = "cemento",
y = "resistencia concreto",
color = "slag"
) +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

ggplot(
df,
aes(x = cement, y=csMPa, color = categoria_water)
) +
geom_point(alpha=0.3) +
geom_smooth(method = "lm", se=FALSE) +
labs(
title = "Interacción entre cement y cuartiles de water",
x = "cemento",
y = "resistencia concreto",
color = "Cuartil water"
) +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

2. Ajuste del modelo

En esta sección se ajustan distintos modelos de regresión lineal múltiple, explorando tanto efectos principales como términos de interacción. Se usa log_csmpa como respuesta para mejorar la linealidad y la normalidad de los residuos.

2.1 Modelos iniciales con interacciones

mlr1 = lm(formula = log_csmpa ~ cement + slag + flyash + water
+ fineaggregate +log_age
+ cement:log_age  + cement:flyash + cement:water
+ water:log_age + water:slag, data=df)
summary(mlr1)
## 
## Call:
## lm(formula = log_csmpa ~ cement + slag + flyash + water + fineaggregate + 
##     log_age + cement:log_age + cement:flyash + cement:water + 
##     water:log_age + water:slag, data = df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1.0156 -0.1260  0.0159  0.1452  0.7293 
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     2.659e+00  3.073e-01   8.654  < 2e-16 ***
## cement          2.975e-03  6.730e-04   4.421 1.09e-05 ***
## slag            1.770e-03  9.419e-04   1.879  0.06048 .  
## flyash          1.524e-03  3.796e-04   4.016 6.36e-05 ***
## water          -1.244e-02  1.560e-03  -7.974 4.12e-15 ***
## fineaggregate   1.390e-04  1.426e-04   0.975  0.32985    
## log_age         4.704e-01  5.200e-02   9.046  < 2e-16 ***
## cement:log_age -7.176e-04  5.907e-05 -12.148  < 2e-16 ***
## cement:flyash   3.501e-06  1.318e-06   2.656  0.00803 ** 
## cement:water    1.526e-05  3.780e-06   4.038 5.80e-05 ***
## water:log_age   2.480e-04  2.637e-04   0.940  0.34726    
## slag:water      5.522e-06  5.192e-06   1.064  0.28780    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2334 on 1018 degrees of freedom
## Multiple R-squared:  0.8227, Adjusted R-squared:  0.8208 
## F-statistic: 429.4 on 11 and 1018 DF,  p-value: < 2.2e-16

El modelo mlr1 incluye:

  • Efectos principales de cement, slag, flyash, water, fineaggregate, log_age.
  • Interacciones entre cemento y otras variables (cement:log_age, cement:flyash, cement:water), y entre agua, edad y escoria (water:log_age, water:slag). Para simplificar el modelo y mantener solo términos relevantes se utiliza un procedimiento stepwise por AIC:
step(mlr1)
## Start:  AIC=-2985.56
## log_csmpa ~ cement + slag + flyash + water + fineaggregate + 
##     log_age + cement:log_age + cement:flyash + cement:water + 
##     water:log_age + water:slag
## 
##                  Df Sum of Sq    RSS     AIC
## - water:log_age   1    0.0482 55.494 -2986.7
## - fineaggregate   1    0.0518 55.498 -2986.6
## - slag:water      1    0.0616 55.508 -2986.4
## <none>                        55.446 -2985.6
## - cement:flyash   1    0.3842 55.830 -2980.4
## - cement:water    1    0.8880 56.334 -2971.2
## - cement:log_age  1    8.0372 63.483 -2848.1
## 
## Step:  AIC=-2986.67
## log_csmpa ~ cement + slag + flyash + water + fineaggregate + 
##     log_age + cement:log_age + cement:flyash + cement:water + 
##     slag:water
## 
##                  Df Sum of Sq    RSS     AIC
## - fineaggregate   1    0.0498 55.544 -2987.7
## - slag:water      1    0.0703 55.565 -2987.4
## <none>                        55.494 -2986.7
## - cement:flyash   1    0.3739 55.868 -2981.8
## - cement:water    1    0.9105 56.405 -2971.9
## - cement:log_age  1    8.0283 63.523 -2849.5
## 
## Step:  AIC=-2987.74
## log_csmpa ~ cement + slag + flyash + water + log_age + cement:log_age + 
##     cement:flyash + cement:water + slag:water
## 
##                  Df Sum of Sq    RSS     AIC
## - slag:water      1    0.0485 55.593 -2988.8
## <none>                        55.544 -2987.7
## - cement:flyash   1    0.4566 56.001 -2981.3
## - cement:water    1    0.8743 56.418 -2973.7
## - cement:log_age  1    8.0723 63.616 -2850.0
## 
## Step:  AIC=-2988.84
## log_csmpa ~ cement + slag + flyash + water + log_age + cement:log_age + 
##     cement:flyash + cement:water
## 
##                  Df Sum of Sq    RSS     AIC
## <none>                        55.593 -2988.8
## - cement:flyash   1     0.496 56.089 -2981.7
## - cement:water    1     0.826 56.419 -2975.7
## - cement:log_age  1     8.099 63.691 -2850.8
## - slag            1    36.842 92.434 -2467.1
## 
## Call:
## lm(formula = log_csmpa ~ cement + slag + flyash + water + log_age + 
##     cement:log_age + cement:flyash + cement:water, data = df)
## 
## Coefficients:
##    (Intercept)          cement            slag          flyash           water  
##      2.507e+00       3.246e-03       2.706e-03       1.388e-03      -1.084e-02  
##        log_age  cement:log_age   cement:flyash    cement:water  
##      5.169e-01      -7.199e-04       3.857e-06       1.332e-05
mlr1.optimo = lm(formula = log_csmpa ~ cement + slag + flyash + water + log_age +
cement:log_age + cement:flyash + cement:water, data = df)

summary(mlr1.optimo)
## 
## Call:
## lm(formula = log_csmpa ~ cement + slag + flyash + water + log_age + 
##     cement:log_age + cement:flyash + cement:water, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.02151 -0.11550  0.01545  0.14552  0.72645 
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     2.507e+00  2.138e-01  11.729  < 2e-16 ***
## cement          3.246e-03  6.362e-04   5.102 4.01e-07 ***
## slag            2.706e-03  1.040e-04  26.012  < 2e-16 ***
## flyash          1.388e-03  3.500e-04   3.966 7.80e-05 ***
## water          -1.084e-02  1.124e-03  -9.644  < 2e-16 ***
## log_age         5.169e-01  1.863e-02  27.739  < 2e-16 ***
## cement:log_age -7.199e-04  5.902e-05 -12.196  < 2e-16 ***
## cement:flyash   3.857e-06  1.278e-06   3.019 0.002602 ** 
## cement:water    1.332e-05  3.418e-06   3.895 0.000104 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2333 on 1021 degrees of freedom
## Multiple R-squared:  0.8222, Adjusted R-squared:  0.8208 
## F-statistic: 590.3 on 8 and 1021 DF,  p-value: < 2.2e-16

mlr1.optimo es una versión más parsimoniosa, que conserva interacciones que parecen relevantes para explicar log_csmpa.

Como comparación, también se ajusta un modelo sin interacciones:

mlr2 = lm(formula = log_csmpa ~ cement + slag + flyash + water
+ fineaggregate +log_age, data=df)
summary(mlr2)
## 
## Call:
## lm(formula = log_csmpa ~ cement + slag + flyash + water + fineaggregate + 
##     log_age, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.31600 -0.12374  0.02711  0.17203  0.73918 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    2.2527006  0.2102143  10.716   <2e-16 ***
## cement         0.0036216  0.0001151  31.452   <2e-16 ***
## slag           0.0027290  0.0001300  20.998   <2e-16 ***
## flyash         0.0025884  0.0001824  14.189   <2e-16 ***
## water         -0.0066219  0.0004922 -13.454   <2e-16 ***
## fineaggregate  0.0001056  0.0001395   0.757    0.449    
## log_age        0.3019171  0.0066860  45.156   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2514 on 1023 degrees of freedom
## Multiple R-squared:  0.7933, Adjusted R-squared:  0.7921 
## F-statistic: 654.3 on 6 and 1023 DF,  p-value: < 2.2e-16
step(mlr2)
## Start:  AIC=-2837.5
## log_csmpa ~ cement + slag + flyash + water + fineaggregate + 
##     log_age
## 
##                 Df Sum of Sq     RSS     AIC
## - fineaggregate  1     0.036  64.679 -2838.9
## <none>                        64.642 -2837.5
## - water          1    11.438  76.080 -2671.7
## - flyash         1    12.722  77.364 -2654.5
## - slag           1    27.862  92.505 -2470.4
## - cement         1    62.507 127.149 -2142.7
## - log_age        1   128.849 193.491 -1710.2
## 
## Step:  AIC=-2838.92
## log_csmpa ~ cement + slag + flyash + water + log_age
## 
##           Df Sum of Sq     RSS     AIC
## <none>                  64.679 -2838.9
## - flyash   1    15.454  80.133 -2620.2
## - water    1    18.967  83.646 -2576.1
## - slag     1    38.201 102.880 -2362.9
## - cement   1    90.005 154.684 -1942.8
## - log_age  1   128.995 193.673 -1711.3
## 
## Call:
## lm(formula = log_csmpa ~ cement + slag + flyash + water + log_age, 
##     data = df)
## 
## Coefficients:
## (Intercept)       cement         slag       flyash        water      log_age  
##    2.396986     0.003572     0.002675     0.002524    -0.006844     0.301642
mlr2.optimo = lm(formula = log_csmpa ~ cement + slag + flyash + water + log_age,
data = df)
summary(mlr2.optimo)
## 
## Call:
## lm(formula = log_csmpa ~ cement + slag + flyash + water + log_age, 
##     data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.31104 -0.12159  0.02827  0.17251  0.73636 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  2.397e+00  8.844e-02   27.10   <2e-16 ***
## cement       3.572e-03  9.463e-05   37.75   <2e-16 ***
## slag         2.675e-03  1.088e-04   24.59   <2e-16 ***
## flyash       2.524e-03  1.614e-04   15.64   <2e-16 ***
## water       -6.844e-03  3.950e-04  -17.33   <2e-16 ***
## log_age      3.016e-01  6.675e-03   45.19   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2513 on 1024 degrees of freedom
## Multiple R-squared:  0.7932, Adjusted R-squared:  0.7922 
## F-statistic: 785.4 on 5 and 1024 DF,  p-value: < 2.2e-16

2.2 Modelo ajustado final sobre csMPa

Para facilitar la interpretación directa en MPa, se ajusta un modelo final usando csMPa como variable respuesta, conservando la estructura de covariables e interacciones seleccionada:

m.optimo = lm(formula = csMPa ~ cement + slag + flyash + water + log_age +
cement:log_age + cement:flyash + cement:water, data = df)
summary(m.optimo)
## 
## Call:
## lm(formula = csMPa ~ cement + slag + flyash + water + log_age + 
##     cement:log_age + cement:flyash + cement:water, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -21.8708  -4.3946  -0.1925   4.2548  29.5265 
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     8.018e+00  6.596e+00   1.216 0.224385    
## cement          1.282e-01  1.963e-02   6.532 1.02e-10 ***
## slag            8.555e-02  3.209e-03  26.655  < 2e-16 ***
## flyash          3.693e-02  1.080e-02   3.420 0.000652 ***
## water          -2.252e-01  3.469e-02  -6.492 1.32e-10 ***
## log_age         9.218e+00  5.750e-01  16.033  < 2e-16 ***
## cement:log_age -1.648e-03  1.821e-03  -0.905 0.365706    
## cement:flyash   1.051e-04  3.942e-05   2.667 0.007781 ** 
## cement:water   -9.288e-05  1.055e-04  -0.881 0.378740    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.2 on 1021 degrees of freedom
## Multiple R-squared:  0.8157, Adjusted R-squared:  0.8143 
## F-statistic: 564.9 on 8 and 1021 DF,  p-value: < 2.2e-16

Interpretación (no trivial) de los coeficientes

Nuestra variable de interés csMPa está medida en MPa (Megapascals). Los coeficientes del modelo pueden interpretarse como:

  • Intercepto:
    • Valor esperado de csMPa cuando todas las covariables son cero. En este contexto, el intercepto no tiene una interpretación física directa (no es realista tener cero edad ni cero componentes), pero es necesario para ajustar el modelo.
  • Cemento (cement = 0.1282):
    • Manteniendo constantes las demás covariables (slag, flyash, water y log_age), un aumento de 1 kg/m³ de cemento se asocia con un incremento promedio de 0.1282 MPa en csMPa.
    • Las mezclas con mayor contenido de cemento tienden a presentar mayor resistencia.
  • Escoria (slag = 0.08555):
    • Un aumento de 1 kg/m³ de slag se asocia con un incremento promedio de 0.08555 MPa en la resistencia, manteniendo constantes las demás variables.
    • Esto indica que la escoria contribuye positivamente al desarrollo de resistencia.
  • Ceniza volante (flyash = 0.03693):
    • Si aumenta en 1 kg/m³ el flyash, se asocia con un incremento promedio de 0.03693 MPa en la resistencia, manteniendo constantes las demás covariables.
  • Agua (water = -0.2252):
    • Si aumenta en 1 kg/m³ el agua, la csMPa disminuye en promedio 0.2252 MPa.
    • Esto es coherente con la teoría: relaciones agua/cemento más altas generan concretos menos resistentes.
  • Edad logarítmica (log_age = 9.218):
    • Un aumento de 1 unidad en log_age (lo cual equivale aproximadamente a multiplicar la edad por 2.718) se asocia con un incremento promedio de 9.218 MPa en csMPa, manteniendo constantes las demás variables.
    • Es decir, la resistencia aumenta claramente con la edad.
  • Interacción cement:log_age (p = 0.3657):
    • Este término indicaría si el efecto del cemento depende de la edad.
    • Sin embargo, no es estadísticamente significativo, por lo que no se evidencia una interacción clara entre ambas variables.
  • Interacción cement:flyash (p = 0.00778):
    • Esta interacción sí es significativa.
    • Indica que el efecto del cemento sobre la resistencia aumenta ligeramente cuando hay más ceniza volante en la mezcla.
  • Interacción cement:water (p = 0.3787):
    • Muestra cómo el efecto del cemento depende del contenido de agua.
    • El término no es significativo, por lo que no se detecta una interacción clara entre cemento y agua.

En general, los valores-p del summary(m.optimo) permiten decidir qué efectos son estadísticamente significativos (por ejemplo, con nivel de significancia 0.05), y el signo de cada coeficiente indica el sentido de la asociación (positivo o negativo).

3. Validación del modelo

Una vez ajustado m.optimo, es fundamental evaluar:

Bondad de ajuste global.

Supuestos del modelo lineal: linealidad, homocedasticidad, normalidad de residuos e independencia.

Presencia de multicolinealidad y valores influyentes.

3.1 Medidas de bondad de ajuste

summary(m.optimo)
## 
## Call:
## lm(formula = csMPa ~ cement + slag + flyash + water + log_age + 
##     cement:log_age + cement:flyash + cement:water, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -21.8708  -4.3946  -0.1925   4.2548  29.5265 
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     8.018e+00  6.596e+00   1.216 0.224385    
## cement          1.282e-01  1.963e-02   6.532 1.02e-10 ***
## slag            8.555e-02  3.209e-03  26.655  < 2e-16 ***
## flyash          3.693e-02  1.080e-02   3.420 0.000652 ***
## water          -2.252e-01  3.469e-02  -6.492 1.32e-10 ***
## log_age         9.218e+00  5.750e-01  16.033  < 2e-16 ***
## cement:log_age -1.648e-03  1.821e-03  -0.905 0.365706    
## cement:flyash   1.051e-04  3.942e-05   2.667 0.007781 ** 
## cement:water   -9.288e-05  1.055e-04  -0.881 0.378740    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.2 on 1021 degrees of freedom
## Multiple R-squared:  0.8157, Adjusted R-squared:  0.8143 
## F-statistic: 564.9 on 8 and 1021 DF,  p-value: < 2.2e-16
AIC(m.optimo)
## [1] 7000.523
BIC(m.optimo)
## [1] 7049.896

3.2 Análisis residual

3.2.1 Gráficos de diagnóstico

par(mfrow = c(2, 2))
plot(m.optimo)

par(mfrow = c(1, 1))

3.2.2 Normalidad de residuos

residuos_modelo <- residuals(m.optimo)
shapiro.test(residuos_modelo)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuos_modelo
## W = 0.99494, p-value = 0.001631

3.2.3 Multicolinealidad

Dado que el modelo incluye términos de interacción, el cálculo estándar del VIF (que evalúa cada término del modelo por separado) puede llevar a interpretaciones erróneas. En presencia de interacciones, los efectos principales y sus términos interactuados están matemáticamente relacionados, por lo que no es adecuado evaluar su colinealidad de manera independiente. Por esta razón, se empleó la opción type = “predictor”, que agrupa correctamente todos los términos asociados a cada predictor original y permite cuantificar la multicolinealidad de forma coherente y consistente con la estructura del modelo.

vif(m.optimo, type = "predictor")
## GVIFs computed for predictors
##               GVIF Df GVIF^(1/(2*Df))         Interacts With
## cement    1.522042  7        1.030458 log_age, flyash, water
## slag      1.522042  1        1.233711                   --  
## flyash  120.885445  3        2.223629                 cement
## water    11.773781  3        1.508294                 cement
## log_age  85.632858  3        2.099456                 cement
##                       Other Predictors
## cement                            slag
## slag    cement, flyash, water, log_age
## flyash            slag, water, log_age
## water            slag, flyash, log_age
## log_age            slag, flyash, water

Al evaluar la colinealidad mediante el GVIF ajustado para modelos con interacciones, todos los predictores presentan valores inferiores a 3, lo cual indica ausencia de colinealidad severa. Las variables flyash y log_age muestran una colinealidad moderada asociada a sus interacciones con cement, pero permanecen dentro de niveles aceptables para su interpretación.

4. Uso del modelo

Finalmente, se utiliza el modelo ajustado para realizar predicciones de la resistencia para nuevas mezclas de concreto, y se calculan:

4.1 Definición de nuevos escenarios

nuevos_datos <- data.frame(
cement = c(300, 450, 250),
slag = c(100, 0, 50),
flyash = c(0, 75, 0),
water = c(180, 165, 170),
age = c(7, 28, 90)
)

nuevos_datos$log_age <- log(nuevos_datos$age)

Cada fila de nuevos_datos representa un diseño de mezcla distinto (cantidades de cemento, escoria, ceniza, agua y edad de curado). ## 4.2 Intervalos de confianza para la media

pred_conf <- predict(m.optimo,
newdata = nuevos_datos,
interval = "confidence",
level = 0.95)

print(cbind(nuevos_datos, pred_conf))
##   cement slag flyash water age  log_age      fit      lwr      upr
## 1    300  100      0   180   7 1.945910 26.46771 25.70337 27.23205
## 2    450    0     75   165  28 3.332205 56.23403 54.87643 57.59164
## 3    250   50      0   170  90 4.499810 41.74955 40.60742 42.89167

4.3 Intervalos de predicción para nuevas observaciones

pred_pred <- predict(m.optimo,
newdata = nuevos_datos,
interval = "prediction",
level = 0.95)

print(cbind(nuevos_datos, pred_pred))
##   cement slag flyash water age  log_age      fit      lwr      upr
## 1    300  100      0   180   7 1.945910 26.46771 12.31896 40.61646
## 2    450    0     75   165  28 3.332205 56.23403 42.04087 70.42720
## 3    250   50      0   170  90 4.499810 41.74955 27.57537 55.92373