Definición del problema objeto de estudio

Este análisis se enmarca en la asesoría solicitada por una compañía internacional, que busca adquirir dos viviendas para ubicar a dos de sus empleados y sus familias en la ciudad de Cali. En concreto, se requiere la compra de: (i) una casa con 200 m² de área construida, 1 parqueadero, 2 baños, 4 habitaciones, en estrato 4 o 5 y ubicada en la zona norte, con un crédito preaprobado de 350 millones; y (ii) un apartamento con 300 m², 3 parqueaderos, 3 baños, 5 habitaciones, en estrato 5 o 6, localizado en la zona sur, con un crédito preaprobado de 850 millones. Para garantizar una búsqueda precisa, se desarrollará un proceso integral que incluye la filtración y generación de subconjuntos de datos, análisis exploratorio mediante mapas interactivos y gráficos de correlación, modelado estadístico a través de regresiones lineales, validación de supuestos y predicción de precios, con el fin último de orientar de manera óptima la selección de propiedades que cumplan con los criterios establecidos.

Análisis Exploratorio

El análisis exploratorio inició con la carga de la base de datos de viviendas, la cual contenía 8,322 registros con información detallada sobre las propiedades en Cali. Se realizó una evaluación inicial del número de valores faltantes por variable, evidenciando que piso presentaba 2,638 valores ausentes (≈ 31 % de los datos), mientras que parqueaderos tenía 1,605 valores faltantes (≈19 %). Para abordar este problema, se implementó una estrategia de imputación diferenciada: dado que parqueaderos es una variable discreta y la ausencia de valores podría interpretarse como la no existencia de parqueaderos en algunas propiedades, se decidió imputar los valores faltantes con cero (0). Por otro lado, la variable piso, al ser de tipo numérico y contar con una relación significativa con otras variables estructurales de la vivienda (areaconst, preciom, banios y habitaciones), fue imputada utilizando el método de Predictive Mean Matching (PMM) a través del paquete mice, permitiendo estimaciones más precisas basadas en valores reales presentes en el conjunto de datos.

Adicionalmente, se llevó a cabo una georreferenciación de las viviendas mediante la intersección de sus coordenadas con los polígonos de barrios y zonas disponibles en el sistema geoespacial de la Alcaldía de Santiago de Cali. Para ello, se utilizó la función st_join() del paquete sf, que permitió asignar a cada observación su correspondiente zona, comuna y barrio a partir de los límites espaciales definidos en los conjuntos de datos geográficos oficiales. Esto último permitió generar un mapa interactivo, que mediante el usos de colores, facilita la visualización de los errores en la asignación de zonas en los datos originales, al compararlos con las zonas determinadas a partir de las coordenadas de cada vivienda y los datos oficiales. Los pop-ups del mapa muestran de manera concisa la información de cada propiedad, lo que permite identificar fácilmente las discrepancias entre la zona asignada en los datos originales y la zona oficial derivada de la georreferenciación.

# Cargar datos
data(vivienda)

zonas <- st_read("~/Workshop/Rproj/Nexus_databases/mc_zonas") %>% 
  st_transform(crs = 4326) %>% 
  mutate(zona_geo =  dplyr::recode(zona_geo,
                           "centro" = "Centro",
                           "centro historico" = "Centro Historico",
                           "norte" = "Norte",
                           "occ" = "Occidente",
                           "ori" = "Oriente",
                           "sur" = "Sur")) %>% 
  select(barrio = NOMBRE, comuna = COD_COMUNA, estratogeo = ESTRATO_MO, zonageo = zona_geo, geometry)

# EDA #####
# Crear data para EDA y posteriores analisis
dat <- vivienda %>% 
  filter(!is.na(id)) %>%
  mutate(
    piso = as.numeric(piso),
    estrato = factor(estrato, ordered = TRUE),
    parqueaderos = if_else(is.na(parqueaderos), 0, parqueaderos)) %>%
  { # imputar datos
    impute_data <- select(., piso, areaconst, preciom, banios, habitaciones)
    imp <- mice(impute_data, m = 1, method = "pmm", seed = 123, printFlag = FALSE)
    imputed <- complete(imp, 1)
    # actualizar 'piso'
    mutate(., piso = imputed$piso)
  } %>%
  st_as_sf(coords = c("longitud", "latitud"), crs = 4326, remove = FALSE) %>% 
  st_join(zonas, join = st_within) %>% 
  rename(barrio = barrio.y) %>% 
  select(id, zonageo,zona, comuna, barrio, tipo, estrato, preciom, areaconst, piso, 
         parqueaderos, banios, habitaciones, longitud, latitud)
# Mapa Exploratorio ####

manual_colors <- c("Centro" = "#E64B35FF",
                   "Norte" = "#4DBBD5FF",
                   "Sur" = "#00A087FF",
                   "Occidente" = "#3C5488FF",
                   "Centro Historico" = "#F39B7FFF",
                   "Oriente" = "#8491B4FF")

leaflet() %>%
  addTiles() %>%
  addMapPane("polygons", zIndex = 410) %>%
  addMapPane("points", zIndex = 420) %>%
  # Polígonos Zona
  addPolygons(
    data = zonas,
    group = "Zonas Oficiales",
    fillColor = ~as.character(manual_colors[zonageo]),
    weight = 1,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    options = pathOptions(pane = "polygons"),
    highlightOptions = highlightOptions(
      weight = 3,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE
    ),
    label = ~paste0("Zona Oficial: ", zonageo, "<br>",
                    "Comuna: ", comuna, "<br>",
                    "Barrio: ", barrio) %>% lapply(htmltools::HTML)
  ) %>%
  # Datos Viviendas
  addCircleMarkers(
    data = dat %>% 
      mutate(zona_recod = dplyr::recode(as.character(zona),
                                        "Zona Centro" = "Centro",
                                        "Zona Norte" = "Norte",
                                        "Zona Sur" = "Sur",
                                        "Zona Oeste" = "Occidente",
                                        "Zona Oriente" = "Oriente")),
    group = "Datos Viviendas",
    lng = ~longitud,
    lat = ~latitud,
    radius = 3,
    stroke = FALSE,
    fillOpacity = 0.8,
    options = pathOptions(pane = "points"),
    color = ~as.character(manual_colors[zona_recod]),
    label = ~paste0("Zona original: ", zona, "<br>",
                    "Zona real: ", zonageo, "<br>",
                    "Tipo: ", tipo, "<br>",
                    "Precio: ", preciom) %>% lapply(htmltools::HTML)
  ) %>%
  # Control de capas
  addLayersControl(
    overlayGroups = c("Zonas Oficiales", "Datos Viviendas"),
    options = layersControlOptions(collapsed = FALSE)
  ) %>%
  addLegend(
    colors = manual_colors,
    labels = names(manual_colors),
    opacity = 0.7,
    title = "Zonas (Comparación)",
    position = "bottomright"
  )

Este análisis geoespacial permitió detectar un sesgo en la asignación de zonas que afecta de manera crítica la búsqueda de propiedades en las áreas de interés, es decir, en las zonas norte y sur. Se evidenció que numerosas viviendas catalogadas originalmente en estas zonas no correspondían a su ubicación real. Por ejemplo, se identificaron propiedades etiquetadas como Zona Sur en los datos originales, que al compararse con la información geográfica oficial, resultaron estar ubicadas en el centro u occidente de la ciudad. Asimismo, se observaron casos inversos, en los que viviendas realmente situadas en la Zona Norte o Sur aparecían asignadas a otras áreas de la ciudad. Estas inconsistencias resaltan la necesidad de corregir el sesgo en la asignación de zonas, ya que, de lo contrario, se podría incurrir en una búsqueda errónea, dirigiendo esfuerzos y recursos hacia áreas que no cumplen con los criterios establecidos para la adquisición de las viviendas solicitadas. La integración de mapas interactivos y la validación cruzada con datos oficiales resultaron esenciales para identificar las propiedades de interés –casas en la zona norte y apartamentos en la zona sur– filtradas según los requerimientos y presentadas en el mapa y tablas a continuación.

Resumen Casas en Zona Norte (Vivienda 1)
Variable Stats / Values Freqs (% of Valid) Graph Missing
id [numeric]
Mean (sd) : 2032 (1639.5)
min ≤ med ≤ max:
83 ≤ 1364 ≤ 6726
IQR (CV) : 2630 (0.8)
586 distinct values 0 (0.0%)
zonageo [character] 1. Norte
586(100.0%)
0 (0.0%)
zona [character]
1. Zona Centro
2. Zona Norte
3. Zona Oeste
4. Zona Oriente
5. Zona Sur
2(0.3%)
528(90.1%)
17(2.9%)
13(2.2%)
26(4.4%)
0 (0.0%)
comuna [character]
1. 02
2. 03
3. 04
4. 05
5. 06
353(60.2%)
3(0.5%)
60(10.2%)
138(23.5%)
32(5.5%)
0 (0.0%)
barrio [character]
1. La Flora
2. Villa del Prado - El Guab
3. Vipasa
4. Urb. La Flora
5. Santa Mónica
6. San Vicente
7. El Bosque
8. Granada
9. Prados del Norte
10. Ciudad Los Alamos
[ 48 others ]
56(9.6%)
52(8.9%)
42(7.2%)
37(6.3%)
34(5.8%)
30(5.1%)
25(4.3%)
24(4.1%)
23(3.9%)
18(3.1%)
245(41.8%)
0 (0.0%)
tipo [character] 1. Casa
586(100.0%)
0 (0.0%)
estrato [ordered, factor]
1. 3
2. 4
3. 5
4. 6
193(32.9%)
122(20.8%)
230(39.2%)
41(7.0%)
0 (0.0%)
preciom [numeric]
Mean (sd) : 440.4 (277)
min ≤ med ≤ max:
100 ≤ 380 ≤ 1800
IQR (CV) : 300 (0.6)
150 distinct values 0 (0.0%)
areaconst [numeric]
Mean (sd) : 262.5 (176.8)
min ≤ med ≤ max:
30 ≤ 237 ≤ 1500
IQR (CV) : 201.2 (0.7)
228 distinct values 0 (0.0%)
piso [numeric]
Mean (sd) : 2.3 (1.4)
min ≤ med ≤ max:
1 ≤ 2 ≤ 12
IQR (CV) : 1 (0.6)
11 distinct values 0 (0.0%)
parqueaderos [numeric]
Mean (sd) : 1.5 (1.6)
min ≤ med ≤ max:
0 ≤ 1 ≤ 10
IQR (CV) : 2 (1.1)
11 distinct values 0 (0.0%)
banios [numeric]
Mean (sd) : 3.5 (1.5)
min ≤ med ≤ max:
0 ≤ 3 ≤ 10
IQR (CV) : 2 (0.4)
11 distinct values 0 (0.0%)
habitaciones [numeric]
Mean (sd) : 4.6 (1.8)
min ≤ med ≤ max:
0 ≤ 4 ≤ 10
IQR (CV) : 2 (0.4)
0:7(1.2%)
2:12(2.0%)
3:134(22.9%)
4:201(34.3%)
5:101(17.2%)
6:47(8.0%)
7:33(5.6%)
8:27(4.6%)
9:13(2.2%)
10:11(1.9%)
0 (0.0%)
longitud [numeric]
Mean (sd) : -76.5 (0)
min ≤ med ≤ max:
-76.5 ≤ -76.5 ≤ -76.5
IQR (CV) : 0 (0)
396 distinct values 0 (0.0%)
latitud [numeric]
Mean (sd) : 3.5 (0)
min ≤ med ≤ max:
3.5 ≤ 3.5 ≤ 3.5
IQR (CV) : 0 (0)
361 distinct values 0 (0.0%)
Resumen Apartamentos en Zona Sur (Vivienda 2)
Variable Stats / Values Freqs (% of Valid) Graph Missing
id [numeric]
Mean (sd) : 3767.2 (1675.5)
min ≤ med ≤ max:
1250 ≤ 3561.5 ≤ 7664
IQR (CV) : 3102.5 (0.4)
1994 distinct values 0 (0.0%)
zonageo [character] 1. Sur
1994(100.0%)
0 (0.0%)
zona [character]
1. Zona Norte
2. Zona Oeste
3. Zona Oriente
4. Zona Sur
72(3.6%)
10(0.5%)
4(0.2%)
1908(95.7%)
0 (0.0%)
comuna [character]
1. 16
2. 17
3. 19
4. 22
26(1.3%)
1485(74.5%)
30(1.5%)
453(22.7%)
0 (0.0%)
barrio [character]
1. Lili
2. Parcelaciones Pance
3. Caney
4. El Ingenio
5. Urb. Ciudad Jardin
6. La Hacienda
7. Urb. Rio Lili
8. Santa Anita - La selva
9. Ciudad Capri
10. Las Quintas de Don Simon
[ 23 others ]
670(33.6%)
258(12.9%)
168(8.4%)
152(7.6%)
133(6.7%)
96(4.8%)
48(2.4%)
40(2.0%)
38(1.9%)
37(1.9%)
354(17.8%)
0 (0.0%)
tipo [character] 1. Apartamento
1994(100.0%)
0 (0.0%)
estrato [ordered, factor]
1. 3
2. 4
3. 5
4. 6
59(3.0%)
730(36.6%)
786(39.4%)
419(21.0%)
0 (0.0%)
preciom [numeric]
Mean (sd) : 318.8 (205.5)
min ≤ med ≤ max:
70 ≤ 260 ≤ 1750
IQR (CV) : 160 (0.6)
300 distinct values 0 (0.0%)
areaconst [numeric]
Mean (sd) : 99.8 (54.8)
min ≤ med ≤ max:
40 ≤ 86 ≤ 932
IQR (CV) : 42 (0.5)
239 distinct values 0 (0.0%)
piso [numeric]
Mean (sd) : 4.5 (2.7)
min ≤ med ≤ max:
1 ≤ 4 ≤ 12
IQR (CV) : 4 (0.6)
12 distinct values 0 (0.0%)
parqueaderos [numeric]
Mean (sd) : 1.2 (0.8)
min ≤ med ≤ max:
0 ≤ 1 ≤ 10
IQR (CV) : 1 (0.7)
0:298(14.9%)
1:1064(53.4%)
2:538(27.0%)
3:64(3.2%)
4:29(1.5%)
10:1(0.1%)
0 (0.0%)
banios [numeric]
Mean (sd) : 2.6 (0.9)
min ≤ med ≤ max:
0 ≤ 2 ≤ 7
IQR (CV) : 1 (0.4)
0:4(0.2%)
1:81(4.1%)
2:1118(56.1%)
3:501(25.1%)
4:181(9.1%)
5:100(5.0%)
6:8(0.4%)
7:1(0.1%)
0 (0.0%)
habitaciones [numeric]
Mean (sd) : 3 (0.6)
min ≤ med ≤ max:
0 ≤ 3 ≤ 6
IQR (CV) : 0 (0.2)
0:6(0.3%)
1:10(0.5%)
2:331(16.6%)
3:1386(69.5%)
4:247(12.4%)
5:13(0.7%)
6:1(0.1%)
0 (0.0%)
longitud [numeric]
Mean (sd) : -76.5 (0)
min ≤ med ≤ max:
-76.6 ≤ -76.5 ≤ -76.5
IQR (CV) : 0 (0)
846 distinct values 0 (0.0%)
latitud [numeric]
Mean (sd) : 3.4 (0)
min ≤ med ≤ max:
3.3 ≤ 3.4 ≤ 3.4
IQR (CV) : 0 (0)
993 distinct values 0 (0.0%)

El análisis exploratorio realizado nos ha permitido evaluar de forma integral la disponibilidad de propiedades en Cali, orientadas a satisfacer los requerimientos de la empresa. En el caso de las casas en la Zona Norte (destinadas a la Vivienda 1), las tablas resumen muestran que la oferta se concentra en estratos 4 y 5 (39.2% y 20.8%, respectivamente), lo que es coherente con las especificaciones requeridas. Sin embargo, el precio promedio de 440.4 millones resulta superior al crédito preaprobado de 350 millones, lo que sugiere un desafío para encontrar opciones dentro del presupuesto; no obstante, el área construida promedio de 262.5 m² se aproxima al valor solicitado, lo que indica que, en términos de dimensiones, la oferta es adecuada. Para los apartamentos en la Zona Sur (Vivienda 2), la mayoría se encuentra en estratos 5 y 6, pero el precio promedio de 318.8 millones, siendo inferior al crédito preaprobado de 850 millones, representa una oportunidad de ahorro en la adquisición; sin embargo, el área construida promedio (99.8 m²) y la dotación de baños y habitaciones (2.6 y 3, respectivamente) son menores a lo requerido, lo que señala que la oferta actual puede no cubrir completamente las especificaciones establecidas. El mapa interactivo nos ha permitido observar de manera visual la distribución espacial de precios y características de las propiedades en ambas zonas, facilitando la identificación de patrones en la viviendas disponibles.

# Mapa Viviendas Requeridas ####

pal_precio <- colorBin("YlOrRd", domain = dat$preciom, 
                       bins = c(50,350,650,850,1500,2000), pretty = FALSE)


leaflet() %>%
  addTiles() %>%
  # Polígonos: Mostrar únicamente las zonas Norte y Sur
  addPolygons(
    data = zonas %>% filter(zonageo %in% c("Norte", "Sur")),
    fillColor = ~ifelse(zonageo == "Norte", manual_colors["Norte"], manual_colors["Sur"]),
    color = "white",
    weight = 1,
    fillOpacity = 0.7,
    popup = ~paste0("<div style='line-height:1.2;'>",
                    "<strong>Zona: </strong>", zonageo, "<br>",
                    "<strong>Comuna: </strong>", comuna, "<br>",
                    "<strong>Barrio: </strong>", barrio,
                    "</div>")
  ) %>%
  # Puntos: Casas en Zona Norte, coloreadas según el precio
  addCircleMarkers(
    data = dat %>% filter(tipo == "Casa", zonageo == "Norte"),
    lng = ~longitud, lat = ~latitud,
    radius = 4,
    stroke = FALSE,
    fillOpacity = 0.9,
    color = ~pal_precio(preciom),
    popup = ~paste0("<div style='line-height:1.2;'>",
                    "<strong>Casa en Zona Norte</strong><br>",
                    "Precio: ", preciom, " millones<br>",
                    "Área Construida: ", areaconst, " m²<br>",
                    "Estrato: ", estrato, "<br>",
                    "Baños: ", banios, "<br>",
                    "Habitaciones: ", habitaciones, "<br>",
                    "Barrio: ", barrio,
                    "</div>")
  ) %>%
  # Puntos: Apartamentos en Zona Sur, coloreados según el precio
  addCircleMarkers(
    data = dat %>% filter(tipo == "Apartamento", zonageo == "Sur"),
    lng = ~longitud, lat = ~latitud,
    radius = 4,
    stroke = FALSE,
    fillOpacity = 0.9,
    color = ~pal_precio(preciom),
    popup = ~paste0("<div style='line-height:1.2;'>",
                    "<strong>Apartamento en Zona Sur</strong><br>",
                    "Precio: ", preciom, " millones<br>",
                    "Área Construida: ", areaconst, " m²<br>",
                    "Estrato: ", estrato, "<br>",
                    "Baños: ", banios, "<br>",
                    "Habitaciones: ", habitaciones, "<br>",
                    "Barrio: ", barrio,
                    "</div>")
  ) %>%
  addLegend(
    pal = pal_precio,
    values = dat$preciom,
    opacity = 0.7,
    title = "Precio de Vivienda (millones)",
    position = "bottomright"
  )

Finalmente, el análisis de correlación evidencia que, en ambos subconjuntos, variables como el área construida y el estrato se correlacionan fuertemente con el precio, siendo en el caso de los apartamentos especialmente relevante la relación entre precio y número de baños. Estos hallazgos fundamentan la selección de variables clave para la construcción del modelo de regresión lineal múltiple, que servirá para predecir los precios y orientar de manera óptima la adquisición de las propiedades que cumplan con los criterios establecidos.

cat('<h5>`Correlación variables`</h5>')
Correlación variables
plot_corr(casas_norte, "Casas en Zona Norte (Vivienda 1)")+
  plot_corr(apartamentos_sur, "Apartamentos en Zona Sur (Vivienda 2)") +
  plot_layout(ncol = 2)

Modelado

Con el fin de predecir el precio de las viviendas y determinar cómo influyen sus principales características, se realizó una fase de modelado que se fundamenta en el análisis exploratorio previo. Tras la depuración inicial de los datos, la imputación de valores faltantes y la reasignación de zonas a partir de datos oficiales, se seleccionaron las variables clave (área construida, estrato, número de baños y número de habitaciones) para ajustar un modelo de regresión lineal múltiple en cada subconjunto de interés. En concreto, se estimaron dos modelos: uno para las Casas en Zona Norte (destinadas a la Vivienda 1) y otro para los Apartamentos en Zona Sur (destinados a la Vivienda 2). Los resultados de estos modelos se presentan en las tablas de comparación de Coeficientes entre Modelos y Ajuste de Modelos, permitiendo evaluar tanto la significancia de cada predictor como la capacidad explicativa y parsimonia de los modelos.

En el modelo de Casas en Zona Norte, el área construida resultó ser un factor determinante: cada metro cuadrado adicional incrementa el precio en aproximadamente 0.833 millones (p < 0.001). El estrato, modelado mediante términos polinómicos, mostró efectos lineales, cuadráticos y cúbicos (con coeficientes de 258.6, 78.4 y 54.8, respectivamente, todos altamente significativos), evidenciando una relación compleja entre la ubicación socioeconómica y el precio. Además, el número de baños contribuye significativamente, con un incremento aproximado de 20.66 millones por cada baño adicional (p = 0.0023), mientras que el número de habitaciones no resultó relevante. Con un 𝑅2 ajustado de 0.664, el modelo explica cerca del 66 % de la variabilidad del precio, lo que es razonable, aunque sugiere que otros factores podrían complementar la explicación.

Por su parte, el modelo para Apartamentos en Zona Sur destaca por un mayor ajuste, con un 𝑅2 ajustado de 0.763, lo que implica que aproximadamente el 76 % de la variabilidad en el precio se explica mediante las variables seleccionadas. En este modelo, el área construida ejerce un efecto aún mayor, incrementando el precio en 1.605 millones por metro cuadrado adicional (p < 0.001). Los efectos polinómicos del estrato también son significativos (coeficientes de 128.8, 77.9 y 23.9), lo que confirma que la ubicación en estratos superiores influye de forma sustancial en la valoración. Destaca asimismo el fuerte impacto del número de baños, ya que cada unidad adicional incrementa el precio en cerca de 60 millones (p < 0.001); curiosamente, el número de habitaciones presenta un efecto negativo y significativo (≈ -12.32, p ≈ 0.0048), lo que podría interpretarse como una compensación en aquellos apartamentos con más habitaciones que, en realidad, disponen de áreas más reducidas.

Comparación de Coeficientes entre Modelos
Modelo term estimate std.error statistic p.value conf.low conf.high
Casas en Zona Norte (Intercept) 203.217 22.739 8.937 0.000 158.556 247.878
Casas en Zona Norte areaconst 0.833 0.049 17.170 0.000 0.738 0.929
Casas en Zona Norte estrato.L 258.600 22.551 11.467 0.000 214.307 302.892
Casas en Zona Norte estrato.Q 78.374 16.502 4.749 0.000 45.963 110.785
Casas en Zona Norte estrato.C 54.801 13.734 3.990 0.000 27.827 81.775
Casas en Zona Norte banios 20.660 6.748 3.062 0.002 7.407 33.912
Casas en Zona Norte habitaciones -0.514 5.137 -0.100 0.920 -10.603 9.575
Apartamentos en Zona Sur (Intercept) 45.058 12.260 3.675 0.000 21.014 69.102
Apartamentos en Zona Sur areaconst 1.605 0.056 28.592 0.000 1.495 1.715
Apartamentos en Zona Sur estrato.L 128.825 10.748 11.986 0.000 107.746 149.903
Apartamentos en Zona Sur estrato.Q 77.876 7.502 10.381 0.000 63.163 92.588
Apartamentos en Zona Sur estrato.C 23.939 4.787 5.001 0.000 14.551 33.327
Apartamentos en Zona Sur banios 59.978 3.791 15.822 0.000 52.543 67.412
Apartamentos en Zona Sur habitaciones -12.324 4.361 -2.826 0.005 -20.877 -3.771
Comparación de Ajuste de Modelos
Modelo r.squared adj.r.squared sigma AIC BIC
Casas en Zona Norte 0.667 0.664 160.656 7624.85 7659.837
Apartamentos en Zona Sur 0.764 0.763 100.012 24033.61 24078.392

Los gráficos diagnósticos de ambos modelos, que incluyen los diagramas de residuos versus valores ajustados, Q–Q plots y Cook’s Distance, evidencian la presencia de algunos valores atípicos (por ejemplo, las observaciones 501, 121 y 290 en el primer modelo; 1026, 750 y 1680 en el segundo). No obstante, en términos generales, la mayoría de los residuos se distribuyen aleatoriamente alrededor de cero, lo que sugiere que los supuestos de linealidad y homocedasticidad se cumplen de forma razonable. En el Q–Q plot se aprecian leves desviaciones en las colas, típicas en muestras grandes, mientras que la gráfica de Scale-Location muestra una dispersión relativamente estable, con una ligera tendencia ascendente para valores ajustados altos. Por último, los puntos con alta Cook’s Distance señalan observaciones influyentes que podrían revisarse en detalle para determinar si representan casos genuinamente atípicos o errores de registro.

cat('<h5>`Diagnóstico Modelo Vivienda 1`</h5>')
Diagnóstico Modelo Vivienda 1
autoplot(modelo_casas, which = 1:4,
                    colour = I("#4DBBD5FF")) +
  theme_minimal()

cat('<h5>`Diagnóstico Modelo Vivienda 2`</h5>')
Diagnóstico Modelo Vivienda 2
autoplot(modelo_apart, which = 1:4,
                    colour = I("#00A087FF")) +
  theme_minimal()

Implementación del Modelo

Tras finalizar el análisis diagnostico y el ajuste de los modelos de regresión, se procede a aplicar los modelos para predecir el precio de las viviendas con las características requeridas. En esta etapa se generan estimaciones para las casas en la Zona Norte y para los apartamentos en la Zona Sur, comparando los precios predichos con los créditos preaprobados, lo que permitirá identificar cuáles propiedades se ajustan mejor a los criterios establecidos por la empresa. Para la Vivienda 1 (Casa en Zona Norte), el modelo estima que, en estrato 4, el precio promedio es de 348.89 millones (con un intervalo de confianza de 314.68 a 383.11 millones), lo que se acerca al límite del crédito preaprobado de 350 millones. En cambio, para estrato 5, la predicción es de 391.02 millones (intervalo de 360.42 a 421.62 millones), superando el presupuesto preaprobado. Esto sugiere que, para cumplir con el límite de 350 millones, sería preferible focalizar la búsqueda en propiedades ubicadas en estrato 4, o bien negociar el precio en caso de opciones en estrato 5.

Predicciones para Vivienda 1 (Casa en Zona Norte)
Estrato 4:
fit lwr upr
348.895 314.681 383.109
Estrato 5:
fit lwr upr
391.021 360.422 421.619

Crédito preaprobado: 350 millones

Por otro lado, para la Vivienda 2 (Apartamento en Zona Sur), el modelo estima un precio de 618.79 millones (intervalo: 593.29 a 644.28 millones) en estrato 5, y de 775.68 millones (intervalo: 749.46 a 801.90 millones) en estrato 6. En ambos casos, los precios estimados se sitúan por debajo del crédito preaprobado de 850 millones, lo que representa una oportunidad de ahorro y una mayor flexibilidad para la negociación.

Predicciones para Vivienda 2 (Apartamento en Zona Sur)
Estrato 5:
fit lwr upr
618.785 593.288 644.283
Estrato 6:
fit lwr upr
775.684 749.465 801.904

Crédito preaprobado: 850 millones

Identificación de Viviendas Requeridas

Con el modelo de regresión lineal múltiple ya ajustado y validado, el siguiente paso consiste en aplicar estos modelos para predecir el precio de las viviendas con las características solicitadas y, a partir de dichas predicciones, sugerir potenciales ofertas que se ajusten al crédito preaprobado (350 millones para casas y 850 millones para apartamentos). Para ello, se agregó a cada registro en los subconjuntos de Casas en Zona Norte y Apartamentos en Zona Sur una columna con el precio predichoa partir del los valores obtenidos de los modelos; posteriormente, se filtraron aquellas propiedades cuyos precios predichos se encuentren dentro de los límites establecidos y que cumplan los requerimientos solicitados. Fue necesario ajustar ciertos requisitos porque, al aplicar las condiciones iniciales, la oferta disponible en la base de datos no arrojaba coincidencias. En el caso de las casas en Zona Norte, por ejemplo, al exigir un precio predicho ≤ 350 millones, al menos 4 habitaciones, 1 parqueadero, 2 baños y 200 m² de área construida, se observó que solo se encontraban casas en estrato 3, lo que contrasta con la intención de focalizar la búsqueda en estratos 4 y 5. Esto sugiere que, en la oferta real, no hay suficientes casas en los estratos deseados dentro del rango de precio estipulado. De manera similar, para los apartamentos en Zona Sur se redujo el número mínimo de habitaciones (de 5 a 4) y el área construida (de 300 a 200 m²) porque, al exigir condiciones tan estrictas, no se obtenían registros; la oferta disponible incluye mayormente propiedades con características ligeramente inferiores a los requerimientos originales, aunque cumplen con el resto de las condiciones.

ofertas_casas <- casas_norte %>%
  mutate(pred = predict(modelo_casas, newdata = .)) %>%
  filter(
    pred <= 350,           # Precio predicho dentro del crédito preaprobado
    habitaciones >= 4,     # Al menos 4 habitaciones
    parqueaderos >= 1,     # Al menos 1 parqueadero
    banios >= 2,           # Al menos 2 baños
    areaconst >= 200       # Al menos 200 m² de área construida
  )

ofertas_apart <- apartamentos_sur %>%
  mutate(pred = predict(modelo_apart, newdata = .)) %>%
  filter(
    pred <= 850,           # Precio predicho dentro del crédito preaprobado
    areaconst >= 200,      # Al menos 200 m² de área construida
    habitaciones >= 4,     # Al menos 4 habitaciones
    parqueaderos >= 3,     # Al menos 3 parqueaderos
    banios >= 3,           # Al menos 3 baños
    estrato %in% c("5", "6")  # Estrato 5 o 6
  )
# Dominios para la escala de precios
dom_casas <- c(50, 350)
dom_apart <- c(50, 850)

# Mapa para Casas en Zona Norte
map_casas <- leaflet() %>%
  addTiles() %>%
  addPolygons(data = zonas %>% filter(zonageo == "Norte"),
              fillColor = as.character(manual_colors["Norte"]),
              weight = 1, opacity = 1, color = "white", fillOpacity = 0.7,
              popup = ~paste("<strong>Zona:</strong>", zonageo, "<br>",
                             "<strong>Comuna:</strong>", comuna, "<br>",
                             "<strong>Barrio:</strong>", barrio)) %>%
  addCircleMarkers(data = ofertas_casas,
                   lng = ~longitud, lat = ~latitud,
                   radius = 4, stroke = FALSE, fillOpacity = 0.9,
                   color = ~pal_precio(pred),
                   popup = ~paste("<strong>Casa en Zona Norte</strong><br>",
                                  "Precio Predicho:", round(pred,1), " millones<br>",
                                  "Área Construida:", areaconst, " m²<br>",
                                  "Estrato:", estrato, "<br>",
                                  "Baños:", banios, "<br>",
                                  "Habitaciones:", habitaciones, "<br>",
                                  "Parqueaderos:", parqueaderos)) %>%
  addLegend("bottomright", pal = pal_precio, values = c(50, 350),
  title = "Precio predicho - Casas", labFormat = labelFormat(suffix = " M"))

# Mapa para Apartamentos en Zona Sur
map_apart <- leaflet() %>%
  addTiles() %>%
  addPolygons(data = zonas %>% filter(zonageo == "Sur"),
              fillColor = as.character(manual_colors["Sur"]),
              weight = 1, opacity = 1, color = "white", fillOpacity = 0.7,
              popup = ~paste("<strong>Zona:</strong>", zonageo, "<br>",
                             "<strong>Comuna:</strong>", comuna, "<br>",
                             "<strong>Barrio:</strong>", barrio)) %>%
  addCircleMarkers(data = ofertas_apart,
                   lng = ~longitud, lat = ~latitud,
                   radius = 4, stroke = FALSE, fillOpacity = 0.9,
                   color = ~pal_precio(pred),
                   popup = ~paste("<strong>Apartamento en Zona Sur</strong><br>",
                                  "Precio Predicho:", round(pred,1), " millones<br>",
                                  "Área Construida:", areaconst, " m²<br>",
                                  "Estrato:", estrato, "<br>",
                                  "Baños:", banios, "<br>",
                                  "Habitaciones:", habitaciones, "<br>",
                                  "Parqueaderos:", parqueaderos)) %>%
  addLegend("bottomright", pal = pal_precio, values = c(50, 850),
  title = "Precio predicho - Apartamentos", labFormat = labelFormat(suffix = " M"))

# Combinar ambos mapas lado a lado
htmltools::browsable(
  tagList(
    tags$div(style = "width: 49%; display: inline-block;", map_casas),
    tags$div(style = "width: 49%; display: inline-block;", map_apart)
  )
)

Con base en el análisis realizado, se identificaron 5 casas en Zona Norte y 8 apartamentos en Zona Sur que, tras ajustar ligeramente los requerimientos iniciales, cumplen con los criterios establecidos y se ajustan al crédito preaprobado. Las casas encontradas presentan un precio predicho inferior o igual a 350 millones, cuentan con al menos 4 habitaciones, 1 parqueadero, 2 baños y un área construida mínima de 200 m²; en este segmento, la oferta es más dispersa, aunque la mayoría de las propiedades se localizan en barrios de la comuna 5. Por su parte, los apartamentos tienen un precio predicho dentro del límite de 850 millones, con al menos 4 habitaciones, 3 parqueaderos, 3 baños y un área construida mínima de 200 m²; los barrios con mayor concentración de oferta en la Zona Sur son “Parcelaciones Pance” y “Urb. Ciudad Jardin”, ambos pertenecientes a la comuna 22. Se recomienda profundizar en la evaluación de estas ofertas mediante una revisión detallada de cada inmueble, considerando tanto sus características cuantitativas como la calidad y ubicación específica, para finalmente seleccionar las propiedades que mejor se ajusten a los requerimientos y maximicen el aprovechamiento del crédito preaprobado.