Introducción

Enunciado

Maria comenzó como agente de bienes raíces en Cali hace 10 años. Después de laborar dos años para una empresa nacional, se traslado a Bogotá y trabajó para otra agencia de bienes raíces. Sus amigos y familiares la convencieron de que con su experiencia y conocimientos del negocio debía abrir su propia agencia. Terminó por adquirir la licencia de intermediario y al poco tiempo fundó su propia compañía, C&A (Casas y Apartamentos) en Cali. Santiago y Lina, dos vendedores de la empresa anterior aceptaron trabajar en la nueva compaña. En la actualidad ocho agentes de bienes raíces colaboran con ella en C&A.

Actualmente las ventas de bienes raíces en Cali se han visto disminuidas de manera significativa en lo corrido del año. Durante este periodo muchas instituciones bancarias de ahorro y vivienda están prestando grandes sumas de dinero para la industria y la construcción comercial y residencial. Cuando el efecto producto de las tensiones políticas y sociales disminuya, se espera que la actividad económica de este sector se reactive.

Hace dos días, María recibió una carta solicitando asesoría para la compra de dos viviendas por parte de una compañía internacional que desea ubicar a dos de sus empleados con sus familias en la ciudad. Las solicitudes incluyen las siguientes condiciones:

Características Vivienda 1 Vivienda 2
Tipo Casa Apartamento
área construida 200 300
parqueaderos 1 3
baños 2 3
habitaciones 4 5
estrato 4 o 5 5 o 6
zona Norte Sur
crédito preaprobado 350 millones 850 millones

Ayude a María a responder la solicitud, mediante técnicas modelación que usted conoce. Ella requiere le envíe un informe ejecutivo donde analice los dos casos y sus recomendaciones (Informe). Como soporte del informe debe anexar las estimaciones, validaciones y comparación de modelos requeridos (Anexos) .

Datos

Los datos de los tres últimos meses se adjuntan en la base que puede obtener con el siguiente código en R

variable descripción
zona ubicación de la vivienda : Zona Centro, Zona Norte,…
piso piso que ocupa la vivienda : primer piso, segundo piso…
estrato estrato socio-económico : 3,4,5,6
preciom precio de la vivienda en millones de pesos
areaconst área construida
parqueaderos número de parqueaderos
banios número de baños
habitaciones número de habitaciones
tipo tipo de vivienda : Casa, Apartamento
barrio barrio de ubicación de la vivienda : 20 de Julio, alamos,..
longitud coordenada geográfica
latitud coordenada geográfica

1. Filtro

Realice un filtro a la base de datos e incluya sólo las ofertas de apartamentos. Presente los primeros 3 registros de las bases y algunas tablas que comprueben la consulta

#librerías
library(paqueteMODELOS)
library(plotly)
library(dplyr)
library(GGally)
library(lmtest)
library(car)
library(Metrics)



# descargar la data
devtools::install_github("centromagis/paqueteMODELOS", force =TRUE)
## stringi     (1.8.3  -> 1.8.4  ) [CRAN]
## rlang       (1.1.3  -> 1.1.4  ) [CRAN]
## cli         (3.6.2  -> 3.6.3  ) [CRAN]
## Rcpp        (1.0.12 -> 1.0.13 ) [CRAN]
## digest      (0.6.34 -> 0.6.37 ) [CRAN]
## curl        (5.2.0  -> 5.2.2  ) [CRAN]
## fastmap     (1.1.1  -> 1.2.0  ) [CRAN]
## backports   (1.4.1  -> 1.5.0  ) [CRAN]
## xfun        (0.41   -> 0.47   ) [CRAN]
## colorspace  (2.1-0  -> 2.1-1  ) [CRAN]
## broom       (1.0.5  -> 1.0.6  ) [CRAN]
## matrixStats (1.2.0  -> 1.4.0  ) [CRAN]
## magick      (2.8.2  -> 2.8.4  ) [CRAN]
## htmltools   (0.5.7  -> 0.5.8.1) [CRAN]
## checkmate   (2.3.1  -> 2.3.2  ) [CRAN]
## yaml        (2.3.8  -> 2.3.10 ) [CRAN]
## knitr       (1.45   -> 1.48   ) [CRAN]
## 
##   There is a binary version available but the source version is later:
##             binary source needs_compilation
## matrixStats  1.3.0  1.4.0              TRUE
## 
##   Binaries will be installed
## package 'stringi' successfully unpacked and MD5 sums checked
## package 'rlang' successfully unpacked and MD5 sums checked
## package 'cli' successfully unpacked and MD5 sums checked
## package 'Rcpp' successfully unpacked and MD5 sums checked
## package 'digest' successfully unpacked and MD5 sums checked
## package 'curl' successfully unpacked and MD5 sums checked
## package 'fastmap' successfully unpacked and MD5 sums checked
## package 'backports' successfully unpacked and MD5 sums checked
## package 'xfun' successfully unpacked and MD5 sums checked
## package 'colorspace' successfully unpacked and MD5 sums checked
## package 'matrixStats' successfully unpacked and MD5 sums checked
## package 'magick' successfully unpacked and MD5 sums checked
## package 'htmltools' successfully unpacked and MD5 sums checked
## package 'checkmate' successfully unpacked and MD5 sums checked
## package 'yaml' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Usuario\AppData\Local\Temp\RtmpAfi95M\downloaded_packages
## ── R CMD build ─────────────────────────────────────────────────────────────────
##       ✔  checking for file 'C:\Users\Usuario\AppData\Local\Temp\RtmpAfi95M\remotes49d829ef134f\Centromagis-paqueteMODELOS-78ce06f/DESCRIPTION' (406ms)
##       ─  preparing 'paqueteMODELOS': (3.3s)
##    checking DESCRIPTION meta-information ...  ✔  checking DESCRIPTION meta-information
##       ─  checking for LF line-endings in source and make files and shell scripts
##       ─  checking for empty or unneeded directories
##       ─  building 'paqueteMODELOS_0.1.0.tar.gz'
##      
## 
data(vivienda)

vivienda_df <- vivienda

Verificar valores únicos

# Verificar valores faltantes en las variables del conjunto de prueba
sapply(vivienda_df, function(x) sum(is.na(x)))
##           id         zona         piso      estrato      preciom    areaconst 
##            3            3         2638            3            2            3 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##         1605            3            3            3            3            3 
##      latitud 
##            3
# Opcional: Filtrar filas que contengan NA en las variables predictoras
vivienda_df <- na.omit(vivienda_df)

# Verificar valores faltantes en las variables del conjunto de prueba
sapply(vivienda_df, function(x) sum(is.na(x)))
##           id         zona         piso      estrato      preciom    areaconst 
##            0            0            0            0            0            0 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##            0            0            0            0            0            0 
##      latitud 
##            0
# Verificar valores únicos en la columna tipo
unique(vivienda_df$tipo)
## [1] "Casa"        "Apartamento"
# Filtrar la base de datos para incluir solo casas en la zona norte
vivienda_filtrada <- vivienda_df %>%
  filter(tipo == "Apartamento")
# Mostrar los primeros 3 registros
head(vivienda_filtrada, 3)
## # A tibble: 3 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1212 Zona N… 01          5     260        90            1      2            3
## 2  1724 Zona N… 01          5     240        87            1      3            3
## 3  2326 Zona N… 01          4     220        52            2      2            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
# Tabla de frecuencias del tipo de vivienda
table(vivienda_filtrada$tipo)
## 
## Apartamento 
##        3182
# Crear un mapa con las ubicaciones de los apartamentos
grafica <- plot_ly(data = vivienda_filtrada, lat = ~latitud, lon = ~longitud, type = 'scattermapbox', mode = 'markers',
               marker = list(size = 10, color = 'red'))

grafica <- grafica %>% layout(
  mapbox = list(
    style = "open-street-map",
    zoom = 10,
    center = list(lat = mean(vivienda_filtrada), lon = mean(vivienda_filtrada$longitud))
  ),
  title = "Ubicación de apartamentos"
)

grafica
# Resumen estadístico de algunas variables de interés
resumen_precio <- summary(vivienda_filtrada$preciom)
print(resumen_precio)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      58     220     300     390     450    1900
resumen_habitaciones <- summary(vivienda_filtrada$habitaciones)
print(resumen_habitaciones)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.000   3.000   3.000   3.023   3.000   7.000

2. Análisis de exploratorio

Realice un análisis exploratorio de datos enfocado en la correlación entre la variable respuesta (precio de la casa) en función del área construida, estrato, numero de baños, numero de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.

# Seleccionar las variables de interés
vivienda_seleccion <- vivienda_filtrada %>%
  select(preciom, areaconst, estrato, banios, habitaciones, zona)

Gráfico de dispersión Precio y Área Construida:

  • El gráfico de dispersión muestra cómo se relacionan el precio y el área construida del apartamernto.

  • Esperamos ver una correlación positiva, donde los precios aumentan a medida que aumenta el área construida.

# 1. Gráfico de dispersión: Precio vs Área construida
grafico_area_precio <- plot_ly(vivienda_seleccion, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers',
                               marker = list(size = 8, color = 'blue', opacity = 0.5)) %>%
  layout(title = 'Relación entre Precio y Área Construida',
         xaxis = list(title = 'Área Construida (m²)'),
         yaxis = list(title = 'Precio (COP)'))

grafico_area_precio

En el gráfico de dispersión que representa la relación entre el precio y el área construida de los apartamentos se observa una tendencia ascendente en este gráfico que indica que a medida que aumenta el tamaño del apartamento, también lo hace el precio. Los valores atípicos que se visualizan pueden correspoder a propiedades de lujo con características especiales o, por el contrario, propiedades que están sobrevaloradas o subvaloradas según su tamaño

Gráfico de cajas y bigotes del precio por cada estrato:

# 2. Gráfico de cajas: Precio vs Estrato
grafico_estrato_precio <- plot_ly(vivienda_seleccion, x = ~factor(estrato), y = ~preciom, type = 'box',
                                  marker = list(color = 'red')) %>%
  layout(title = 'Distribución del precio por estrato',
         xaxis = list(title = 'Estrato'),
         yaxis = list(title = 'Precio (COP)'))

grafico_estrato_precio

El gráfico de cajas muestra que los estratos más altos presentan precios de vivienda más elevados lo que se puede visualizar por tener cajas más altas en el gráfico. La mediana indica el precio típico de un apartamento en cada estrato por ejemplo para el estrato 3 el valor típico es 130 millones mientras en el estrato 6 es de 600 millones. La anchura de la caja del estrato 6 por ejemplo representa la variabilidad de los precios pueden tener una mezcla de viviendas de diferentes tamaños y caracteristicas que se traduce en una dispersión mayor de los precios. Los valores atípicos altos que se presentan en cada estrato pueden corrresponder corresponder a propiedades de lujo que, a pesar de estar en un estrato medio, son excepcionales por su tamaño, diseño, o características únicas.

Gráfico de cajas y bigotes del precio por el número de baños:

# 3. Gráfico de cajas: Precio vs Número de Baños
grafico_banos_precio <- plot_ly(vivienda_seleccion, x = ~factor(banios), y = ~preciom, type = 'box',
                                marker = list(color = 'green')) %>%
  layout(title = 'Distribución del precio por número de baños',
         xaxis = list(title = 'Número de Baños'),
         yaxis = list(title = 'Precio (COP)'))

grafico_banos_precio

El gráfico de cajas que representa la distribución del precio por número de baños permite visualizar cómo el precio de los apartamentos varía en función de la cantidad de baños, es decir que los apartamentos con más baños tienden a tener precios más altos. Más baños suelen estar asociados con propiedades más grandes o de mayor lujo, lo que incrementa su valor.

Gráfica de cajas y bigotes del precio por número de habitaciones:

# 4. Gráfico de cajas: Precio vs Número de Habitaciones
grafico_habitaciones_precio <- plot_ly(vivienda_seleccion, x = ~factor(habitaciones), y = ~preciom, type = 'box',
                                       marker = list(color = 'orange')) %>%
  layout(title = 'Distribución del precio por número de habitaciones',
         xaxis = list(title = 'Número de Habitaciones'),
         yaxis = list(title = 'Precio (COP)'))

grafico_habitaciones_precio

El gráfico de cajas ofrece una visión clara de cómo el precio de los apartamentos varía según la cantidad de habitaciones que tienen. Esto se debe a que más habitaciones suelen implicar una mayor área construida, más comodidades, y por lo tanto, un mayor valor en el mercado.

Gráfico de cajas y bigotes del precio por zona:

# 5. Gráfico de cajas: Precio vs Zona
grafico_zona_precio <- plot_ly(vivienda_seleccion, x = ~zona, y = ~preciom, type = 'box',
                               marker = list(color = 'purple')) %>%
  layout(title = 'Distribución del Precio por Zona',
         xaxis = list(title = 'Zona'),
         yaxis = list(title = 'Precio (COP)'))

grafico_zona_precio
  • El gráfico de cajas permite observar que la zona más costosa de cali es el Oeste pero igualmente hay mayor dispersión en el precio de los apartamentos.
# Calcular la matriz de correlación para las variables seleccionadas
variables_de_interes <- c('preciom', 'areaconst', 'estrato', 'banios', 'habitaciones')
correlaciones <- cor(vivienda_filtrada[, variables_de_interes], use = "complete.obs")

# Visualizar la matriz de correlación utilizando un heatmap interactivo
plot_ly(
  z = correlaciones, 
  x = colnames(correlaciones), 
  y = colnames(correlaciones), 
  type = "heatmap", 
  colorscale = "Viridis"  # Opción para una escala de color más atractiva
) %>%
  layout(
    title = "Matriz de Correlación entre Variables",
    xaxis = list(title = "Variables"),
    yaxis = list(title = "Variables")
  )

La matriz de correlación visualizada nos permite entender cómo se relacionan las distintas variables entre sí. El gráfico utiliza una escala de colores que va del magenta (baja correlación) al amarillo (alta correlación).

3. Modelo de Regresión lineal

Estime un modelo de regresión lineal múltiple con las variables del punto anterior (precio = f(área construida, estrato, número de cuartos, número de parqueaderos, número de baños ) ) e interprete los coeficientes si son estadísticamente significativos. Las interpretaciones deber están contextualizadas y discutir si los resultados son lógicos. Adicionalmente interprete el coeficiente R2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).

# Verificar las variables disponibles
colnames(vivienda_filtrada)
##  [1] "id"           "zona"         "piso"         "estrato"      "preciom"     
##  [6] "areaconst"    "parqueaderos" "banios"       "habitaciones" "tipo"        
## [11] "barrio"       "longitud"     "latitud"
# Seleccionar las variables de interés
modelo_data <- vivienda_filtrada[, c("preciom", "estrato", "habitaciones", "parqueaderos", "banios", "areaconst")]
# Estimación del modelo
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = modelo_data)

# Resumen del modelo
summary(modelo)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = modelo_data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1609.23   -55.44    -0.01    47.99   963.98 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -285.9869    17.5604  -16.29   <2e-16 ***
## areaconst       1.9061     0.0549   34.72   <2e-16 ***
## estrato        52.5560     3.4642   15.17   <2e-16 ***
## habitaciones  -35.3350     4.2623   -8.29   <2e-16 ***
## parqueaderos  100.3163     4.9734   20.17   <2e-16 ***
## banios         53.5608     3.8771   13.81   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 133.5 on 3176 degrees of freedom
## Multiple R-squared:  0.7823, Adjusted R-squared:  0.7819 
## F-statistic:  2282 on 5 and 3176 DF,  p-value: < 2.2e-16

El valor del intercepto es -285.98 es el valor estimado del precio cuando las demas variables son cero, esto práctica esto no tiene sentido.

EL valor 1.9 en areasconst indica que por cada metro cuadrado adicional en el área construida, se espera que el precio de la vivienda aumente en promedio en 1.9 millones, manteniendo constantes las demás variables y va en línea que a mayor área construida incrementa el precio de la vivienda.

El valor 52.55 en estrato indica que por cada aumento en un nivel del estrato, se espera que el precio de la vivienda aumente en promedio en 52.55 millones, manteniendo constantes las demás variables.

EL valor negativo -35.33 de habitaciones sugiere una disminución en el precio de la vivienda a medida que aumenta el número de habitaciones, teniendo en cuenta esto es necesario validar porque podría indicar que el número de habitaciones no necesariamente incrementa el valor de la vivienda, o que hay una relación no lineal o interacción con otras variables no modeladas. Sería importante validar si exite una multicolinealidad entre el númeor de habitaciones y otras variables como el areaconst y se esté compensando la variablidad. Otro aspecto que puede estar pasando es que la realción entre el precio del apartamento y numero de habitaciones no sea lineal por ejemplo incrememntar habitaciones en un apartamento grande puede que no icremente el precio como en un apartamento pequeño.

Respecto a parqueaderos y baños se peude decir que los valores son lógicos teneindo en cuenta que los parqueaderos son una caraterística valiosa y los baños aportan comodidad y valor a los apartamentos

Los coeficientes tienen p-valores < 0.001,lo que indica que estas variables tienen un impacto en el precio de la vivienda.

El R-squared de 0.7823 indica que el 78.23% de la variabilidad en el precio de la vivienda es explicada por las variables incluidas en el modelo. Esto sugiere que el modelo tiene un buen ajuste.

El R-squared ajustado de 0.7819 un poco menor pero sugiere que la inclusión de más variables no está sobre ajustando el modelo.

  • Para mejorarlo es posible reivsar si se pueden incluir otras variables, validar las interacciones entre las variables independientes. Por ejemplo, la interacción entre estrato y área construida podría tener un impacto importante en el precio y mejorar la capacidad predictiva del modelo. Revisar si la relación entre el precio y alguna de las variables no es lineal, un modelo no lineal podría mejorar el ajuste.

4. Validación de supuestos

Realice la validación de supuestos del modelo e interprete los resultados (no es necesario corregir en caso de presentar problemas, solo realizar sugerencias de que se podría hacer).

a. Supuesto de linealidad

par(mfrow = c(2, 2))
plot(modelo)

b. Supuesto de Homocedasticidad

La homocedasticidad implica que la variabilidad de los residuos es constante a lo largo de los valores ajustados.

bptest(modelo)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo
## BP = 1066.8, df = 5, p-value < 2.2e-16

Interpretación: Un p-valor extremadamente bajo indica que existe heterocedasticidad. Una posible solución sería aplicar transformaciones a la variable dependiente, como tomar el logaritmo de preciom.

c. Supuesto de Normalidad de los Residuos

shapiro.test(modelo$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  modelo$residuals
## W = 0.82899, p-value < 2.2e-16

El p-value < 2.2e-16 rechaza la hipótesis nula de normalidad de los residuos, lo que quiere decir que, los residuos no siguen una distribución normal

d. Supuesto de Independencia de los errores

# Test de Durbin-Watson
library(lmtest)
dwtest(modelo)
## 
##  Durbin-Watson test
## 
## data:  modelo
## DW = 1.5868, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0

Interpretación: El p-valor es menor que 0.05, lo que indica que hay evidencia significativa para rechazar la hipótesis nula de no autocorrelación en los residuos. Por consiguiente en el modelo existe autocorrelación positiva en los residuos. Para abordar este problema de autocorrelación en los residuos se podría agregar nuevas variables al modelo o se podría transformar variables que ya están en el modelo..

5. Partición de datos

Realice una partición en los datos de forma aleatoria donde 70% sea un set para entrenar el modelo y 30% para prueba. Estime el modelo con la muestra del 70%. Muestre los resultados

# Establecer la semilla para reproducibilidad
set.seed(123)

# Partición del 70% de los datos para entrenamiento y 30% para prueba
sample_size <- floor(0.7 * nrow(vivienda_filtrada))

# Crear índices aleatorios
train_indices <- sample(seq_len(nrow(vivienda_filtrada)), size = sample_size)

# Crear el set de entrenamiento y prueba
train_data <- vivienda_filtrada[train_indices, ]
test_data <- vivienda_filtrada[-train_indices, ]

# Estimar el modelo con los datos de entrenamiento
# Estimación del modelo
modelo_entrenamiento <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = train_data)

# Mostrar los resultados del modelo
summary(modelo_entrenamiento)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = train_data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1206.30   -52.70     0.72    47.73   949.70 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -275.85441   20.87286 -13.216  < 2e-16 ***
## areaconst       2.11600    0.06812  31.062  < 2e-16 ***
## estrato        49.66599    4.08581  12.156  < 2e-16 ***
## habitaciones  -35.53463    5.10337  -6.963 4.37e-12 ***
## parqueaderos   93.05787    5.98705  15.543  < 2e-16 ***
## banios         50.82708    4.64058  10.953  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 132.5 on 2221 degrees of freedom
## Multiple R-squared:  0.791,  Adjusted R-squared:  0.7905 
## F-statistic:  1681 on 5 and 2221 DF,  p-value: < 2.2e-16

Este modelo tiene un buen ajuste, pero los coeficientes como el de las habitaciones sugieren que hay factores no modelados que podrían influir en los resultados.

6. Predicciones

Realice predicciones con el modelo anterior usando los datos de prueba (30%)

# Realizar predicciones sobre el set de prueba utilizando el modelo entrenado
predicciones <- predict(modelo_entrenamiento, newdata = test_data)

# Mostrar las primeras 6 predicciones junto con los valores reales
resultados <- data.frame(Valor_Real = test_data$preciom, Prediccion = predicciones)
head(resultados)
##   Valor_Real Prediccion
## 1        220  214.00766
## 2        320  383.33087
## 3        420  559.91076
## 4        170  163.78733
## 5         78   30.59933
## 6       1130  899.51209

7. Error cuadrático medio

Calcule el error cuadrático medio, el error absoluto medio y el R2, interprete

# Calcular el Error Cuadrático Medio (MSE)
mse <- mse(test_data$preciom, predicciones)

# Calcular el Error Absoluto Medio (MAE)
mae <- mae(test_data$preciom, predicciones)

# Calcular el R²
r2 <- 1 - sum((test_data$preciom - predicciones)^2) / sum((test_data$preciom - mean(test_data$preciom))^2)

# Mostrar los resultados
cat("Error Cuadrático Medio (MSE):", mse, "\n")
## Error Cuadrático Medio (MSE): 18724.53
cat("Error Absoluto Medio (MAE):", mae, "\n")
## Error Absoluto Medio (MAE): 81.80488
cat("R² en el conjunto de prueba:", r2, "\n")
## R² en el conjunto de prueba: 0.7561123

El modelo tiene un buen desempeño, con un alto valor de R2, lo que indica que la mayoría de las variaciones en los precios de las viviendas están explicadas por las variables incluidas en el modelo. Sin embargo, el MSE y el MAE muestran que aún hay errores en las predicciones, lo cual podría mejorarse con variables adicionales o ajustes en el modelo.