knitr::opts_chunk$set(message = FALSE, warning = FALSE)
library(paqueteMODELOS)
library(tidyverse)
library(FactoMineR)
library(factoextra)
library(cluster)
library(dplyr)
library(knitr) 
library(kableExtra)
library(tibble)
library(tidyr)

data("vivienda")

head(vivienda)
## # A tibble: 6 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1147 Zona O… <NA>        3     250        70            1      3            6
## 2  1169 Zona O… <NA>        3     320       120            1      2            3
## 3  1350 Zona O… <NA>        3     350       220            2      2            4
## 4  5992 Zona S… 02          4     400       280            3      5            3
## 5  1212 Zona N… 01          5     260        90            1      2            3
## 6  1724 Zona N… 01          5     240        87            1      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Paso 1. Filtrado de 3 filas de tipo casa y zona norte

base1 <- vivienda %>% filter(tipo=="Casa", zona=="Zona Norte")
por <- head(base1, 3)


kable(por, caption = "Filtrado 3 filas tipo casa y zona norte") %>%
kable_styling(bootstrap_options = c("striped"))
Filtrado 3 filas tipo casa y zona norte
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1209 Zona Norte 02 5 320 150 2 4 6 Casa acopi -76.51341 3.47968
1592 Zona Norte 02 5 780 380 2 3 3 Casa acopi -76.51674 3.48721
4057 Zona Norte 02 6 750 445 NA 7 6 Casa acopi -76.52950 3.38527
# Conteo por tipo
table(base1$tipo)
## 
## Casa 
##  722
# Conteo por zona
table(base1$zona)
## 
## Zona Norte 
##        722
library(ggplot2)


library(plotly)

plot_ly(data = base1, 
        lat = ~latitud, lon = ~longitud, 
        type = "scattermapbox", mode = "markers",
        text = ~paste("Barrio:", barrio,
                      "<br>Precio:", preciom, "millones",
                      "<br>Area:", areaconst, "m2",
                      "<br>Estrato:", estrato),
        marker = list(size = 12, color = "blue")) %>%
  layout(
    mapbox = list(
      style = "open-street-map",
      zoom = 10.5,
      center = list(
        lat = mean(base1$latitud, na.rm = TRUE),
        lon = mean(base1$longitud, na.rm = TRUE)
      )
    ),
    title = "Viviendas en Zona Norte"
  )

Como se ve en el grafico de Potly, casi todas las viviendas se encuentran espacialmente en la zona norte, sin embargo existen algunas las cuales la categoría no coincide con la ubicación espacial real, al encontrarse en otras zonas de la ciudad, por lo tanto se puede inferir que existieron algunos errores de digitación.

2. Analisis exploratorio

library(plotly)

plot_ly(data = base1, x = ~areaconst, y = ~preciom,
        type = "scatter", mode = "markers",
        color = ~estrato, text = ~paste("Baños:", banios, "<br>Habitaciones:", habitaciones)) %>%
  layout(title = "Precio vs Área construida",
         xaxis = list(title = "Área construida (m²)"),
         yaxis = list(title = "Precio (millones)"))

Relación precio vs área construida

Existe una correlación lineal entre al area y el precio. Entre mayor area, suele haber en promedio un mayor precio por casa.

base1 %>%
  group_by(estrato) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE)) %>%
   mutate(estrato = as.factor(estrato)) %>%
  plot_ly(x = ~estrato, y = ~precio_prom, type = "bar") %>%
  layout(title = "Precio promedio por estrato",
         xaxis = list(title = "Estrato"),
         yaxis = list(title = "Precio promedio (millones)"))

Precio promedio x estrato

base1 %>%
  group_by(banios) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE)) %>%
  mutate(banios = as.factor(banios)) %>%
  plot_ly(x = ~banios, y = ~precio_prom, type = "bar") %>%
  layout(title = "Precio promedio por número de baños",
         xaxis = list(title = "Baños"))

Precio promedio por numero de baños

base1 %>%
  group_by(habitaciones) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE)) %>%
   mutate(habitaciones = as.factor(habitaciones)) %>%
  plot_ly(x = ~habitaciones, y = ~precio_prom, type = "bar") %>%
  layout(title = "Precio promedio por numero de habitaciones",
         xaxis = list(title = "Habitaciones"),
         yaxis = list(title = "Precio promedio (millones)"))

Precio promedio por numero de habitaciones

base1 %>%
  group_by(barrio) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE)) %>%
  plot_ly(x = ~barrio, y = ~precio_prom, type = "bar") %>%
  layout(title = "Precio promedio por zona/barrio")

Precio promedio por barrios en zona Norte

El análisis exploratorio muestra que el precio de las casas está fuertemente correlacionado con el área construida y el estrato socioeconómico. Las variables baños y habitaciones también influyen, aunque con mayor variabilidad. La zona geográfica confirma diferencias en el valor promedio de las viviendas, lo que evidencia la importancia de la ubicación en la valoración inmobiliaria.

Por otro lado en variables como Baños y habitaciones, se encuentran casos en los que el valor es 0, por lo tanto se puede inferir a que se dió un error en la digitación o recolección de datos.

3 Modelo de regresión lineal múltiple

modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios,
             data = base1)

summary(modelo)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = base1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -784.29  -77.56  -16.03   47.67  978.61 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -238.17090   44.40551  -5.364 1.34e-07 ***
## areaconst       0.67673    0.05281  12.814  < 2e-16 ***
## estrato        80.63495    9.82632   8.206 2.70e-15 ***
## habitaciones    7.64511    5.65873   1.351    0.177    
## parqueaderos   24.00598    5.86889   4.090 5.14e-05 ***
## banios         18.89938    7.48800   2.524    0.012 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 155.1 on 429 degrees of freedom
##   (287 observations deleted due to missingness)
## Multiple R-squared:  0.6041, Adjusted R-squared:  0.5995 
## F-statistic: 130.9 on 5 and 429 DF,  p-value: < 2.2e-16

Área construida (0.6767, p < 0.001)
Cada metro cuadrado adicional aumenta el precio en 0.67 millones en promedio. Es altamente significativo y lógico: más área construida, mayor precio.

Estrato (80.63, p < 0.001)
Subir un nivel de estrato incrementa el precio en 80 millones en promedio. Muy significativo y consistente con la realidad: estratos más altos implican zonas más costosas.

Habitaciones (7.64, p = 0.177)
Aunque el coeficiente sugiere que cada habitación adicional aumenta el precio en 7.6 millones, no es estadísticamente significativo. Esto puede deberse a que el número de habitaciones está correlacionado con el área construida.

Parqueaderos (24.00, p < 0.001)
Cada parqueadero adicional aumenta el precio en 24 millones. Significativo y lógico: más parqueaderos, mayor valor percibido.

Baños (18.90, p = 0.012)
Cada baño adicional aumenta el precio en 19 millones. Es significativo y razonable: más baños, mayor comodidad y precio.

R² = 0.6041 (60%)
El modelo explica el 60% de la variabilidad del precio. Es un ajuste aceptable en datos inmobiliarios, pero deja un 40% sin explicar.

R² ajustado = 0.5995
Similar al R², lo que indica que las variables incluidas realmente aportan al modelo.

F-statistic p < 0.001
El modelo en conjunto es altamente significativo.

El modelo muestra que el precio de las casas está principalmente determinado por el área construida y el estrato socioeconómico. Variables como número de baños y parqueaderos también resultan significativas, mientras que el número de habitaciones no aporta información adicional. El R² indica que el modelo explica un 60% de la variabilidad del precio, lo cual es razonable pero sugiere que existen otros factores relevantes no incluidos en el análisis

4. Validación de supuestos del modelo

plot(modelo, which = 1)  # Residuals vs Fitted

El gráfico de residuos vs valores ajustados muestra que el modelo cumple con el supuesto de linealidad, aunque se observan indicios de heterocedasticidad y algunos valores influyentes. Esto sugiere que el modelo predice mejor en rangos medios de precio y presenta mayor error en extremos. Para mejorar el ajuste, podrían aplicarse transformaciones de la variable respuesta

plot(modelo, which = 2)  # QQ plot

El QQ-plot muestra que los residuos del modelo siguen razonablemente una distribución normal, aunque se observan desviaciones en las colas y algunos valores extremos. Esto sugiere que el supuesto de normalidad se cumple en términos generales, pero la presencia de outliers podría afectar la precisión de las pruebas de significancia. Una posible mejora sería aplicar transformaciones a la variable respuesta o utilizar modelos robustos

plot(modelo, which = 3)  # Scale-Location

El Scale-Location plot muestra que los residuos no presentan una varianza constante, lo que indica heterocedasticidad. Esto sugiere que el modelo tiene mayor error en ciertos rangos de precio, especialmente en los extremos. Aunque el modelo sigue siendo útil, una posible mejora sería aplicar transformaciones a la variable respuesta o utilizar técnicas robustas para reducir el impacto de la heterocedasticidad

library(lmtest)
dwtest(modelo)
## 
##  Durbin-Watson test
## 
## data:  modelo
## DW = 1.7615, p-value = 0.005472
## alternative hypothesis: true autocorrelation is greater than 0

La prueba de Durbin-Watson arrojó un valor de 1.76 con un p-value de 0.005, lo que indica presencia de autocorrelación positiva en los residuos. Esto sugiere que el modelo no cumple completamente con el supuesto de independencia, posiblemente debido a factores espaciales o variables omitidas. Aunque el modelo sigue siendo válido para explicar el precio, las inferencias estadísticas deben interpretarse con precaución. Una posible mejora sería incluir variables adicionales de ubicación o aplicar modelos robustos que consideren dependencia espacial.

library(car)
vif(modelo)
##    areaconst      estrato habitaciones parqueaderos       banios 
##     1.460998     1.307757     1.721015     1.226334     1.967421

El análisis de multicolinealidad mediante el cálculo de los VIF muestra valores entre 1.2 y 1.9, muy por debajo del umbral crítico de 10. Esto indica que las variables explicativas no presentan problemas de colinealidad severa. Aunque el número de habitaciones está correlacionado con el área construida, la magnitud de esta relación no afecta de manera significativa la estabilidad del modelo.

5. Predicción con la primera solicitud

# Definir las características de la vivienda
nueva_vivienda1 <- data.frame(
  areaconst = 200,
  estrato = 4,          # 
  habitaciones = 4,
  parqueaderos = 1,
  banios = 2
)

# Usar el modelo ajustado para predecir
prediccion1 <- predict(modelo, newdata = nueva_vivienda1)

# Mostrar resultado
prediccion1
##       1 
## 312.101
nueva_vivienda2 <- data.frame(
  areaconst = 200,
  estrato = 5,          # 
  habitaciones = 4,
  parqueaderos = 1,
  banios = 2
)

# Usar el modelo ajustado para predecir
prediccion2 <- predict(modelo, newdata = nueva_vivienda2)

# Mostrar resultado
prediccion2
##        1 
## 392.7359

La predicción del modelo para una vivienda con área construida de 200 m², 1 parqueadero, 2 baños, 4 habitaciones y ubicada en la zona norte arroja un precio estimado de 312,1 millones si pertenece al estrato 4, y de 392,7 millones si pertenece al estrato 5. Dado que el crédito preaprobado es de 350 millones, la compra sería viable en estrato 4, pero insuficiente en estrato 5.

6. Selección de 5 viviendas potenciales

library(dplyr)
library(plotly)

# Filtrar ofertas potenciales
ofertas <- base1 %>%
  filter(zona == "Zona Norte",
         areaconst >= 180 & areaconst <= 220,
         estrato %in% c(4,5),
         parqueaderos == 1,
         banios == 2,
         habitaciones == 4,
         preciom <= 350) %>%
  slice_head(n = 5)   # tomar las primeras 5

# Ver las ofertas seleccionadas
ofertas
## # A tibble: 0 × 13
## # ℹ 13 variables: id <dbl>, zona <chr>, piso <chr>, estrato <dbl>,
## #   preciom <dbl>, areaconst <dbl>, parqueaderos <dbl>, banios <dbl>,
## #   habitaciones <dbl>, tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
ofertas <- base1 %>%
  filter(zona == "Zona Norte",
         areaconst >= 170 & areaconst <= 210,
         estrato %in% c(3,4,5),
         parqueaderos %in% c(1,2),
         banios %in% c(2,3),
         habitaciones %in% c(3,4,5),
         preciom <= 350) %>%
  arrange(desc(areaconst)) %>% 
  slice_head(n = 5)

# Ver las ofertas seleccionadas
kable(ofertas, caption = "Ofertas potenciales en zona norte") %>%
kable_styling(bootstrap_options = c("striped"))
Ofertas potenciales en zona norte
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1151 Zona Norte NA 5 320 210 2 3 5 Casa urbanización la merced -76.51200 3.47600
1270 Zona Norte NA 5 350 203 2 2 5 Casa el bosque -76.51448 3.48531
1887 Zona Norte 01 5 340 203 2 3 4 Casa vipasa -76.51803 3.48257
612 Zona Norte 01 3 270 196 1 2 4 Casa calima -76.49994 3.48465
1352 Zona Norte NA 5 350 190 1 3 3 Casa la flora -76.51538 3.48796
# Crear mapa interactivo con plotly
library(plotly)

plot_ly(data = ofertas, 
        lat = ~latitud, lon = ~longitud, 
        type = "scattermapbox", mode = "markers",
        text = ~paste("Barrio:", barrio,
                      "<br>Precio:", preciom, "millones",
                      "<br>Area:", areaconst, "m2",
                      "<br>Estrato:", estrato),
        marker = list(size = 12, color = "blue")) %>%
  layout(
    mapbox = list(
      style = "open-street-map",
      zoom = 10.5,
      center = list(
        lat = mean(ofertas$latitud, na.rm = TRUE),
        lon = mean(ofertas$longitud, na.rm = TRUE)
      )
    ),
    title = "Ofertas potenciales Zona Norte"
  )

No se encontraron viviendas que cumplieran estrictamente con las condiciones solicitadas y el crédito máximo de 350 millones. Esto sugiere que la empresa debe considerar flexibilizar criterios (ej. área, número de baños o parqueaderos) o aumentar el crédito disponible para acceder a opciones en la zona norte. Flexibilizando, podemos encontrar 5 opciones de viviendas, que pueden considerarse, pero que sin embargo no cumplen estrictamente con los criterios establecidos.

7. Realice los pasos del 1 al 6. Para la segunda solicitud que tiene un crédito pre-aprobado por valor de $850 millones.

Realizamos el filtrado de la base con la especificación de que sea tipo apartamento y en la zona Sur de la ciudad.

base2 <- vivienda %>% filter(tipo=="Apartamento", zona=="Zona Sur")
por <- head(base2, 3)

kable(por, caption = "Filtrado 3 filas tipo Apartamento y zona Sur") %>%
kable_styling(bootstrap_options = c("striped"))
Filtrado 3 filas tipo Apartamento y zona Sur
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
5098 Zona Sur 05 4 290 96 1 2 3 Apartamento acopi -76.53464 3.44987
698 Zona Sur 02 3 78 40 1 1 2 Apartamento aguablanca -76.50100 3.40000
8199 Zona Sur NA 6 875 194 2 5 3 Apartamento aguacatal -76.55700 3.45900
# Conteo por tipo
table(base2$tipo)
## 
## Apartamento 
##        2787
# Conteo por zona
table(base2$zona)
## 
## Zona Sur 
##     2787
library(plotly)

plot_ly(data = base2, 
        lat = ~latitud, lon = ~longitud, 
        type = "scattermapbox", mode = "markers",
        text = ~paste("Barrio:", barrio,
                      "<br>Precio:", preciom, "millones",
                      "<br>Area:", areaconst, "m2",
                      "<br>Estrato:", estrato),
        marker = list(size = 12, color = "blue")) %>%
  layout(
    mapbox = list(
      style = "open-street-map",
      zoom = 10.5,
      center = list(
        lat = mean(base2$latitud, na.rm = TRUE),
        lon = mean(base2$longitud, na.rm = TRUE)
      )
    ),
    title = "Viviendas en Zona Sur"
  )

Como se ve en el grafico de Potly, la mayor parte de las viviendas se encuentran espacialmente en la zona Sur, sin embargo existen algunas las cuales la categoría no coincide con la ubicación espacial real, al encontrarse en otras zonas de la ciudad, por lo tanto se puede inferir que existieron algunos errores de digitación.

7.2 Analisis exploratorio

plot_ly(data = base2, x = ~areaconst, y = ~preciom,
        type = "scatter", mode = "markers",
        color = ~estrato, text = ~paste("Baños:", banios, "<br>Habitaciones:", habitaciones)) %>%
  layout(title = "Precio vs Área construida",
         xaxis = list(title = "Área construida (m²)"),
         yaxis = list(title = "Precio (millones)"))

Relación precio vs área construida en apartamentos de zona Sur

Existe una correlación lineal entre al area y el precio. Entre mayor area, suele haber en promedio un mayor precio por casa.

base2 %>%
  group_by(estrato) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE)) %>%
   mutate(estrato = as.factor(estrato)) %>%
  plot_ly(x = ~estrato, y = ~precio_prom, type = "bar") %>%
  layout(title = "Precio promedio por estrato",
         xaxis = list(title = "Estrato"),
         yaxis = list(title = "Precio promedio (millones)"))

Precio promedio x estrato en apartamentos de zona Sur

base2 %>%
  group_by(banios) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE)) %>%
  mutate(banios = as.factor(banios)) %>%
  plot_ly(x = ~banios, y = ~precio_prom, type = "bar") %>%
  layout(title = "Precio promedio por número de baños",
         xaxis = list(title = "Baños"))

Precio promedio por numero de baños en apartamentos de zona Sur.

base2 %>%
  group_by(habitaciones) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE)) %>%
   mutate(habitaciones = as.factor(habitaciones)) %>%
  plot_ly(x = ~habitaciones, y = ~precio_prom, type = "bar") %>%
  layout(title = "Precio promedio por numero de habitaciones",
         xaxis = list(title = "Habitaciones"),
         yaxis = list(title = "Precio promedio (millones)"))

Precio promedio por numero de habitaciones en apartamentos de zona sur.

base2 %>%
  group_by(barrio) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE)) %>%
  plot_ly(x = ~barrio, y = ~precio_prom, type = "bar") %>%
  layout(title = "Precio promedio por zona/barrio")

El análisis exploratorio muestra que el precio de las casas está fuertemente correlacionado con el área construida y el estrato socioeconómico. Las variables baños y habitaciones también influyen, aunque con mayor variabilidad. La zona geográfica confirma diferencias en el valor promedio de las viviendas, lo que evidencia la importancia de la ubicación en la valoración inmobiliaria.

Por otro lado en variables como Baños y habitaciones, se encuentran casos en los que el valor es 0, por lo tanto se puede inferir a que se dió un error en la digitación o recolección de datos.

7.3 Modelo de regresión lineal múltiple

modelo2 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios,
             data = base2)

summary(modelo2)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = base2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1092.02   -42.28    -1.33    40.58   926.56 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -261.62501   15.63220 -16.736  < 2e-16 ***
## areaconst       1.28505    0.05403  23.785  < 2e-16 ***
## estrato        60.89709    3.08408  19.746  < 2e-16 ***
## habitaciones  -24.83693    3.89229  -6.381 2.11e-10 ***
## parqueaderos   72.91468    3.95797  18.422  < 2e-16 ***
## banios         50.69675    3.39637  14.927  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 98.02 on 2375 degrees of freedom
##   (406 observations deleted due to missingness)
## Multiple R-squared:  0.7485, Adjusted R-squared:  0.748 
## F-statistic:  1414 on 5 and 2375 DF,  p-value: < 2.2e-16

Área construida (1.285, p < 0.001)
Cada metro cuadrado adicional aumenta el precio en 1.28 millones en promedio. Es altamente significativo y lógico: más área, mayor precio.

Estrato (60.90, p < 0.001)
Subir un nivel de estrato incrementa el precio en 61 millones en promedio. Muy significativo y consistente con la realidad: estratos más altos implican zonas más costosas.

Habitaciones (-24.83, p < 0.001)
Aquí aparece algo interesante: cada habitación adicional reduce el precio en 24.8 millones en promedio. Esto puede deberse a que, en apartamentos, más habitaciones suelen implicar menor área por habitación (menos lujo, menos amplitud).

También puede reflejar que el mercado valora más el área total que el número de cuartos.

Parqueaderos (72.91, p < 0.001)
Cada parqueadero adicional aumenta el precio en 73 millones. Muy significativo: en apartamentos, el parqueadero es un factor clave de valorización.

Baños (50.70, p < 0.001)
Cada baño adicional aumenta el precio en 51 millones. Significativo y lógico: más baños, mayor comodidad y valor percibido.

R² = 0.7485 (75%)
El modelo explica el 75% de la variabilidad del precio. Es un ajuste muy bueno para datos inmobiliarios.

R² ajustado = 0.748
Prácticamente igual, lo que indica que las variables incluidas aportan de manera consistente.

F-statistic p < 0.001
El modelo en conjunto es altamente significativo.

El modelo de regresión para apartamentos en la zona sur muestra que el precio está principalmente determinado por el área construida y el estrato socioeconómico. Variables como número de parqueaderos y baños también resultan altamente significativas y con gran impacto en el precio. En contraste, el número de habitaciones presenta un efecto negativo, lo que sugiere que en apartamentos el mercado valora más la amplitud y distribución que la cantidad de cuartos. El modelo explica el 75% de la variabilidad del precio, lo cual representa un ajuste sólido y confiable

7.4 Validación de supuestos del modelo en apartamentos de zona Sur

plot(modelo2, which = 1)  # Residuals vs Fitted

El gráfico de residuos vs valores ajustados muestra que el modelo cumple con el supuesto de linealidad, aunque se observan indicios de heterocedasticidad y algunos valores influyentes. Esto sugiere que el modelo predice mejor en rangos medios de precio y presenta mayor error en extremos. Para mejorar el ajuste, podrían aplicarse transformaciones de la variable respuesta

plot(modelo2, which = 2)  # QQ plot

El QQ-plot muestra que los residuos del modelo siguen razonablemente una distribución normal, aunque se observan desviaciones en las colas y algunos valores extremos. Esto sugiere que el supuesto de normalidad se cumple en términos generales, pero la presencia de outliers podría afectar la precisión de las pruebas de significancia. Una posible mejora sería aplicar transformaciones a la variable respuesta o utilizar modelos robustos.

plot(modelo2, which = 3)  # Scale-Location

El Scale-Location plot muestra que los residuos no presentan una varianza constante, lo que indica heterocedasticidad. Esto sugiere que el modelo tiene mayor error en ciertos rangos de precio, especialmente en los extremos. Aunque el modelo sigue siendo útil, una posible mejora sería aplicar transformaciones a la variable respuesta o utilizar técnicas robustas para reducir el impacto de la heterocedasticidad

dwtest(modelo2)
## 
##  Durbin-Watson test
## 
## data:  modelo2
## DW = 1.5333, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0

La prueba de Durbin-Watson arrojó un valor de 1.53 con un p-value de 0.005, lo que indica presencia de autocorrelación positiva en los residuos. Esto sugiere que el modelo no cumple completamente con el supuesto de independencia, posiblemente debido a factores espaciales o variables omitidas. Aunque el modelo sigue siendo válido para explicar el precio, las inferencias estadísticas deben interpretarse con precaución. Una posible mejora sería incluir variables adicionales de ubicación o aplicar modelos robustos que consideren dependencia espacial.

7.5 Predecir el precio de la vivienda con las características de la segunda solicitud

# Definir las características de la vivienda
nueva_apartamento1 <- data.frame(
  areaconst = 300,
  estrato = 5,          # 
  habitaciones = 5,
  parqueaderos = 3,
  banios = 3
)

# Usar el modelo ajustado para predecir
prediccion1 <- predict(modelo, newdata = nueva_apartamento1)

# Mostrar resultado
prediccion1
##        1 
## 534.9658
nueva_apartamento2 <- data.frame(
  areaconst = 300,
  estrato = 6,          # 
  habitaciones = 5,
  parqueaderos = 3,
  banios = 3
)


# Usar el modelo ajustado para predecir
prediccion2 <- predict(modelo, newdata = nueva_apartamento2)

# Mostrar resultado
prediccion2
##        1 
## 615.6008

La predicción del modelo para una vivienda con área construida de 300 m², 3 parqueadero, 3 baños, 5 habitaciones y ubicada en la zona sur arroja un precio estimado de 534,9 millones si pertenece al estrato 5, y de 615,6 millones si pertenece al estrato 6. Dado que el crédito preaprobado es de 850 millones, la compra sería viable en ambos estratos.

7.6 Cinco ofertas potenciales

# Filtrar ofertas potenciales
ofertas <- base2 %>%
  filter(
         areaconst >= 300 & areaconst <= 350,
         estrato %in% c(5,6),
         parqueaderos >=3,
         banios >= 3,
         habitaciones >=5,
         preciom <= 850) %>%
  arrange(desc(areaconst)) %>%
  slice_head(n = 5)   # tomar las primeras 5

# Ver las ofertas seleccionadas

kable(ofertas, caption = "Ofertas potenciales zona Sur") %>%
kable_styling(bootstrap_options = c("striped"))
Ofertas potenciales zona Sur
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
7512 Zona Sur NA 5 670 300 3 5 6 Apartamento seminario -76.55 3.409
# Crear mapa interactivo con plotly
library(plotly)

plot_ly(data = ofertas, 
        lat = ~latitud, lon = ~longitud, 
        type = "scattermapbox", mode = "markers",
        text = ~paste("Barrio:", barrio,
                      "<br>Precio:", preciom, "millones",
                      "<br>Area:", areaconst, "m2",
                      "<br>Estrato:", estrato),
        marker = list(size = 12, color = "blue")) %>%
  layout(
    mapbox = list(
      style = "open-street-map",
      zoom = 10.5,
      center = list(
        lat = mean(ofertas$latitud, na.rm = TRUE),
        lon = mean(ofertas$longitud, na.rm = TRUE)
      )
    ),
    title = "Ofertas potenciales en zona Sur"
  )
# Filtrar ofertas potenciales
ofertas2 <- base2 %>%
  filter(
         areaconst >= 250 & areaconst <= 450,
         estrato %in% c(4,5,6),
         parqueaderos >=2,
         banios >= 2,
         habitaciones >=4,
         preciom <= 850) %>% 
  arrange(desc(areaconst)) %>% 
  slice_head(n = 5)   # tomar las primeras 5

# Ver las ofertas seleccionadas
kable(ofertas2, caption = "Ofertas potenciales zona Sur") %>%
kable_styling(bootstrap_options = c("striped"))
Ofertas potenciales zona Sur
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
6932 Zona Sur NA 5 500 330.00 2 4 4 Apartamento san fernando -76.54600 3.43500
7658 Zona Sur 06 5 520 320.00 2 4 4 Apartamento cuarto de legua -76.55100 3.40900
7512 Zona Sur NA 5 670 300.00 3 5 6 Apartamento seminario -76.55000 3.40900
8113 Zona Sur 02 5 410 295.55 2 4 4 Apartamento cuarto de legua -76.55527 3.40750
5306 Zona Sur 12 5 650 275.00 2 5 5 Apartamento ciudadela pasoancho -76.53569 3.38597
# Crear mapa interactivo con plotly
plot_ly(data = ofertas2, 
        lat = ~latitud, lon = ~longitud, 
        type = "scattermapbox", mode = "markers",
        text = ~paste("Barrio:", barrio,
                      "<br>Precio:", preciom, "millones",
                      "<br>Area:", areaconst, "m2",
                      "<br>Estrato:", estrato),
        marker = list(size = 12, color = "blue")) %>%
  layout(
    mapbox = list(
      style = "open-street-map",
      zoom = 10.5,
      center = list(
        lat = mean(ofertas2$latitud, na.rm = TRUE),
        lon = mean(ofertas2$longitud, na.rm = TRUE)
      )
    ),
    title = "Ofertas potenciales en zona Sur"
  )

Se encontró unicamente una vivienda que cumplía estrictamente con las condiciones solicitadas y el crédito máximo de 850 millones. Esto sugiere que la empresa debe considerar flexibilizar criterios (ej. área, número de baños o parqueaderos) o aumentar el crédito disponible para acceder a opciones en la zona norte. Flexibilizando, podemos encontrar 5 opciones de viviendas, que pueden considerarse, pero que sin embargo no cumplen estrictamente con los criterios establecidos.

8. Conclusiones finales

Importancia del área y estrato

En ambos modelos (casas en zona norte y apartamentos en zona sur), el área construida y el estrato socioeconómico son las variables más determinantes del precio.

Esto confirma que el mercado inmobiliario valora principalmente el tamaño y la ubicación socioeconómica.

Variables secundarias

Parqueaderos y baños también tienen un impacto significativo y positivo en el precio, reflejando la importancia de la comodidad y la infraestructura.

En el caso de las casas, habitaciones no resultó significativa; en apartamentos, incluso mostró un efecto negativo, lo que sugiere que el mercado valora más la amplitud que la cantidad de cuartos.

Calidad del ajuste

El modelo de casas explicó un 60% de la variabilidad del precio (R² ≈ 0.60).

El modelo de apartamentos tuvo un ajuste mucho más sólido, explicando cerca del 75% (R² ≈ 0.75).

Esto indica que el comportamiento de precios en apartamentos está mejor capturado por las variables incluidas.

Supuestos del modelo

Se detectó heterocedasticidad y autocorrelación positiva en los residuos, lo que sugiere que existen patrones no capturados (posiblemente espaciales o de barrio).

Aunque los modelos son útiles, las inferencias deben interpretarse con cautela.

Predicciones y viabilidad de compra

En la primera solicitud (casa zona norte, crédito 350 millones), el modelo predijo precios de 312 millones (estrato 4) y 393 millones (estrato 5).

La compra sería viable en estrato 4, pero insuficiente en estrato 5.

En la segunda solicitud (apartamento zona sur, crédito 850 millones), el rango de precios estimados se ajusta mejor al crédito disponible, mostrando más opciones viables.

Selección de ofertas

El filtrado estricto no arrojó resultados, lo que obligó a flexibilizar criterios.

Esto evidencia que los parámetros de búsqueda deben ser realistas frente al mercado, y que la empresa debe considerar ampliar rangos o ajustar el crédito.