Caris Chia Amaya
Modelos Estadísticos para la toma de decisiones Maestría en Ciencia de
Datos
Pontificia Universidad Javeriana de Cali
La Alcaldía de Santiago de Cali, a través de su portal de Planeación, ha publicado un documento de referencia denominado Zonas Geográficas IDESC, cuyo objetivo principal es ofrecer a los usuarios una aproximación de la división geográfica de la ciudad. Tal como se indica en el mismo portal, esta delimitación no es de carácter oficial ni está respaldada en ningún marco normativo; más bien, busca orientar al ciudadano sobre la ubicación aproximada de un punto o sector de la ciudad.
En dicha publicación, la Zona Norte de Cali se describe como el territorio que va desde la Carrera 1 (KR 1) entre la Calle 1 Oeste (CL 1 OESTE) hasta el separador vial ubicado entre la Calle 25 (CL 25) y la Calle 26 (CL 26). A partir de este punto, el trazado continúa por la Carrera 7 (KR 7), siguiendo el corredor férreo hasta llegar a la Calle 88 (CL 88). Desde allí, se prolonga hacia el norte por el límite del suelo urbano hasta volver al punto de inicio en la Carrera 1.
Bajo esta definición aproximada, se elaboró un polígono que recoge las coordenadas geográficas de cada vértice de la zona descrita. Para su creación, se utilizó la herramienta disponible en Google Maps Draw Shape React, la cual permite dibujar manualmente el contorno sobre el mapa, exportar las coordenadas (latitud y longitud) de cada punto y así construir una capa geográfica que delimite la Zona Norte con un mayor grado de precisión que el mero uso de etiquetas textuales.
Una vez obtenido el polígono, se procedió a realizar un filtro espacial en la base de datos de viviendas, manteniendo únicamente aquellas propiedades cuyas coordenadas (latitud y longitud) se encuentran dentro del límite poligonal definido. Este criterio se mostró más consistente y fiable para identificar si un inmueble está efectivamente en la Zona Norte, en comparación con la variable “zona” que aparece en la base de datos, la cual a veces no coincide con la posición geográfica real por posibles errores de clasificación o definiciones ambiguas. En ese orden de ideas, se encontraron 212 viviendas que la data indicaba como Zona Norte, pero quedaron fuera del polígono, este polígono puede tener mejoras pero en términos generales hace una mejor delimitación.
Nota: El gráfico es interactivo por lo que basta con tocar cada uno de los puntos para ver los datos específicos del inmueble.
# Contar el número de registros antes de eliminar NAs
n_total <- nrow(vivienda)
# Eliminar filas con NA en 'longitud' o 'latitud'
vivienda <- vivienda %>%
filter(!is.na(longitud) & !is.na(latitud))
# Contar el número de registros después del filtro
n_filtrados <- nrow(vivienda)
# Convertir la base de datos a objeto sf
vivienda_sf <- st_as_sf(vivienda, coords = c("longitud", "latitud"), crs = 4326)
# 1. Crear el data frame con las coordenadas del polígono de la Zona Norte
zonaNorte_coords <- data.frame(
lat = c(3.4900304891034377, 3.4902339589114146, 3.490822950212433, 3.4923864526015884, 3.492846935685632, 3.4936501033148653, 3.4937893189673783, 3.493746483384189, 3.4934573431465252, 3.4925149595314817, 3.4919580960415617, 3.4908872037865812, 3.490683734120075, 3.490994293067019, 3.491358396529218, 3.48980560136964, 3.4898805639535473, 3.491358396529218, 3.4924614149794984, 3.4926755931691265, 3.4930718226910953, 3.49313607611133, 3.4944532702567423, 3.496509374494677, 3.497494589511154, 3.4978908169975935, 3.497321146421177, 3.4963359312224407, 3.495586310269127, 3.4946652744803144, 3.493696119837062, 3.493281388063734, 3.492494283484646, 3.4925424735798845, 3.4944540120287844, 3.4947485064016393, 3.4947592152861744, 3.4950314432595238, 3.495781064656296, 3.4960969763512133, 3.495358064084629, 3.4952242031044785, 3.495165304267168, 3.495058215462579, 3.4945067079253596, 3.493885592252606, 3.4942336312578113, 3.4946191512359537, 3.4951760131469447, 3.495285779157687, 3.495778782065353, 3.495880894853365, 3.496876819390565, 3.497605021608466, 3.498365349791154, 3.4991363861915543, 3.5001001807998517, 3.5004535719077845, 3.5013209858801115, 3.501717211748297, 3.501909970218145, 3.501909970218145, 3.5019206790208504, 3.5025846245500523, 3.5036126683112725, 3.5033342399041265, 3.503719756138133, 3.504330156517178, 3.505026226638858, 3.5054438684632614, 3.5055081210350765, 3.505401033412929, 3.505497412273413, 3.505722296242591, 3.504779924962706, 3.5038375527335144, 3.5025846245500523, 3.50102113916572, 3.4997789160405977, 3.4991470950260024, 3.49834393210432, 3.4978620340209354, 3.4971231231452475, 3.4964377560152973, 3.496277123021766, 3.495795223876051, 3.4952544256510234, 3.4946306332517567, 3.494356214055474, 3.4937859655385455, 3.493044374225896, 3.493052669686557, 3.492294796608607, 3.491692317249437, 3.4906214246913745, 3.4896147845735546, 3.488811613493228, 3.4884475090440277, 3.4872159782440604, 3.485971967940531, 3.4847404338985997, 3.483551734294502, 3.4827913941208175, 3.481902544970222, 3.481131494425043, 3.480724550827301, 3.480007044581939, 3.4789147205921482, 3.4779616133315017, 3.4769335414981724, 3.4760125595290385, 3.4750915766606862, 3.4742669749576, 3.4732174808389265, 3.4726064335203652, 3.4696185796982815, 3.4688261007550127, 3.4682707166302955, 3.4679280226260856, 3.4650954377421654, 3.4640217416042076, 3.4623671635371718, 3.4610927616311513, 3.460162341060184, 3.4596001038280595, 3.4583042796037957, 3.457768814531154, 3.457277676455672, 3.45647447786384, 3.4561528826267622, 3.4555852883526867, 3.455296136422134, 3.4547124776272375, 3.454016370338333, 3.453529094932381, 3.4536736711778326, 3.454407261417267, 3.45584231221696, 3.4569507268340596, 3.458931947801667, 3.459317482211437, 3.460072486642976, 3.460356282479434, 3.4604419566775046, 3.4603830556671635, 3.4600885505605214, 3.4596012782739947, 3.459237773375063, 3.4587505006511328, 3.4582471637282666, 3.4574439659575398, 3.4573467405605967, 3.4568166296049023, 3.456340064957493, 3.4560455585950414, 3.4579792998394767, 3.460185413504977, 3.4626913810493996, 3.463226843340138, 3.4637408868543216, 3.463869397689249, 3.464447696230534, 3.4658184765463664, 3.4674676939814315, 3.4692454186445736, 3.470872003275005, 3.4718144085515465, 3.472564048440877, 3.472938868162376, 3.472960286427676, 3.473153050793547, 3.4742346723386364, 3.474181126746764, 3.4743631817467677, 3.4747701280903587, 3.4748450918713503, 3.4750057285248603, 3.4767834389973338, 3.4779078926865687, 3.4783362556439887, 3.479225108159585, 3.48001757837017, 3.482202222525706, 3.4831231984451954, 3.483476595942532, 3.4855862691506627, 3.48603604658323, 3.4850294015552183, 3.4851793274787215, 3.4859503747078797, 3.486614331537605, 3.487406795527153, 3.487813736235208, 3.4885954902590095, 3.489580713582015, 3.4900304891034377),
lng = c(-76.53934690128393, -76.53933617244788, -76.53791996608801, -76.53809162746496, -76.53725477825232, -76.53648230205603, -76.5362784541709, -76.53458329807349, -76.53432580600806, -76.53341385494299, -76.53322073589392, -76.53255554805823, -76.53206202159949, -76.53181525837012, -76.53030249248572, -76.52917596469946, -76.52892920147009, -76.52848931919165, -76.52838203083105, -76.52760955463476, -76.52756663929053, -76.52389737735815, -76.5238866485221, -76.52461620937414, -76.5243372596366, -76.52362915645666, -76.52187662292653, -76.5184863107317, -76.51588993240529, -76.51261795582062, -76.50883067669159, -76.5075539452005, -76.50498975338226, -76.5049253803659, -76.50620747627502, -76.50555301727539, -76.5055787710725, -76.50491894765484, -76.5031808762132, -76.50246740861523, -76.50215090795147, -76.50191487355816, -76.50171102567303, -76.50154472871411, -76.50100828691113, -76.50038601441968, -76.50008024259198, -76.49981202169049, -76.49936677499402, -76.49928362651455, -76.49899115281515, -76.49843794958295, -76.4980517114848, -76.49759037153424, -76.49722559110822, -76.49722559110822, -76.4971504892558, -76.49681789533795, -76.4967535223216, -76.49683935301007, -76.4966998781413, -76.49607760564984, -76.4955304350108, -76.49520856992902, -76.49456483976545, -76.49437172071637, -76.49397475378217, -76.49399621145429, -76.49429661886396, -76.49438244955243, -76.49399621145429, -76.49334175245465, -76.49297697202863, -76.49178607122602, -76.49183971540631, -76.49182898657025, -76.49172169820966, -76.49159295217694, -76.49105651037397, -76.49001581327619, -76.48861033575238, -76.48712975637616, -76.48602468626203, -76.48530585424604, -76.48509664194287, -76.48467285291852, -76.4842919792384, -76.48406667368116, -76.4839540129805, -76.48377698718552, -76.48394596635346, -76.4839452297328, -76.48417456006489, -76.48414237355671, -76.48411018704853, -76.4839063391634, -76.48363811826191, -76.48363811826191, -76.48326260899982, -76.48288411418734, -76.4825515202695, -76.48215455333529, -76.48200434963046, -76.4814357213193, -76.48073834697543, -76.48007315913974, -76.47945088664828, -76.47926849643527, -76.47923630992709, -76.47906464855014, -76.47845310489474, -76.47766989986239, -76.47690815250216, -76.47645754138766, -76.47638243953524, -76.47662920276461, -76.47632879535495, -76.47586171186138, -76.47684340036083, -76.48569883233746, -76.48905973646812, -76.49425722070222, -76.49830299440887, -76.50117982151701, -76.50297090188964, -76.50709825170092, -76.50887923848681, -76.51048408557018, -76.51286588717541, -76.51397632170757, -76.51550518084606, -76.51621928448624, -76.51662161583847, -76.51698103184647, -76.5176515841002, -76.51845088238663, -76.51956668133683, -76.52001729245133, -76.52033915753312, -76.52086487050003, -76.52094192008964, -76.52114576797477, -76.52124232749931, -76.52137107353202, -76.52159101467124, -76.52219182949058, -76.52319497566215, -76.52397756876016, -76.52495389284158, -76.52597313226724, -76.5273893386271, -76.5275878220942, -76.52853732408548, -76.52970676721597, -76.53054898084665, -76.53229807688837, -76.53515194728021, -76.53854225947504, -76.53862809016351, -76.53802727534418, -76.53697584941034, -76.53551672770624, -76.53485153987054, -76.53422926737909, -76.53328512980585, -76.53239132592851, -76.53176905343706, -76.53140427301103, -76.53146864602739, -76.53216602037126, -76.53229476640398, -76.53227330873186, -76.53250190387793, -76.53287741314001, -76.53296324382849, -76.53245898853369, -76.53104278217383, -76.53037759433813, -76.52930471073218, -76.52920815120764, -76.52950855861731, -76.5295622027976, -76.52962657581396, -76.53214785228796, -76.53215858112402, -76.5328023112876, -76.5341541446311, -76.53517338405676, -76.53546306263037, -76.53539868961401, -76.53504463802405, -76.53605314861365, -76.53675052295752, -76.5373942531211, -76.53876754413672, -76.53934690128393)
)
# 2. Convertir las coordenadas en un objeto sf de polígono
coords_mat <- cbind(zonaNorte_coords$lng, zonaNorte_coords$lat)
coords_mat <- rbind(coords_mat, coords_mat[1, ]) # Cerrar el polígono
zonaNorte_polygon <- st_polygon(list(coords_mat))
zonaNorte_sfc <- st_sfc(zonaNorte_polygon, crs = 4326)
# Validar y corregir el polígono
zonaNorte_sfc <- st_make_valid(zonaNorte_sfc)
# 3. Convertir la base de datos de viviendas a objeto sf (asegúrate de que 'vivienda' esté cargada)
vivienda_sf <- st_as_sf(vivienda, coords = c("longitud", "latitud"), crs = 4326)
# 4. Filtrar las viviendas que están dentro del polígono de la Zona Norte (filtrado espacial)
vivienda_norte_sf <- vivienda_sf %>%
filter(lengths(st_within(geometry, zonaNorte_sfc)) > 0)
# 5. Si solo deseas casas, filtra por la variable 'tipo'
casas_norte_sf <- vivienda_norte_sf %>%
filter(tipo == "Casa")
# 6. Además, obtener las casas que la data dice que son de Zona Norte pero quedaron fuera del polígono (filtrado por atributo y espacial inverso)
casas_norte_outside_sf <- vivienda_sf %>%
filter(tipo == "Casa", zona == "Zona Norte") %>%
filter(lengths(st_within(geometry, zonaNorte_sfc)) == 0)
# 7. Crear una paleta de colores según estrato para las casas dentro del polígono
pal_estrato <- colorFactor(
palette = c("blue", "green", "red", "orange", "purple", "brown"),
domain = casas_norte_sf$estrato
)
# 8. Visualizar en un mapa interactivo con leaflet
leaflet() %>%
addTiles() %>%
# Agregar el polígono de la Zona Norte
addPolygons(
data = zonaNorte_sfc,
fillColor = "blue",
fillOpacity = 0.1,
color = "blue",
weight = 2,
popup = "Zona Norte"
) %>%
# Agregar marcadores para las casas dentro del polígono (con colores según estrato)
addCircleMarkers(
data = casas_norte_sf,
popup = ~paste(
"<strong>Barrio:</strong>", barrio, "<br/>",
"<strong>Precio:</strong>", preciom, "millones<br/>",
"<strong>Área construida:</strong>", areaconst, "m²<br/>",
"<strong>Parqueaderos:</strong>", parqueaderos, "<br/>",
"<strong>Baños:</strong>", banios, "<br/>",
"<strong>Habitaciones:</strong>", habitaciones
),
radius = 4,
fillColor = ~pal_estrato(estrato),
color = "white",
weight = 1,
fillOpacity = 0.8,
group = "Dentro del polígono"
) %>%
# Agregar marcadores para las casas que la data dice que son de Zona Norte pero quedaron fuera del polígono
addCircleMarkers(
data = casas_norte_outside_sf,
popup = ~paste(
"<strong>Barrio:</strong>", barrio, "<br/>",
"<strong>Precio:</strong>", preciom, "millones<br/>",
"<strong>Área construida:</strong>", areaconst, "m²<br/>",
"<strong>Parqueaderos:</strong>", parqueaderos, "<br/>",
"<strong>Baños:</strong>", banios, "<br/>",
"<strong>Habitaciones:</strong>", habitaciones,
"<br/><em>Fuera del polígono</em>"
),
radius = 4,
fillColor = "gray",
color = "white",
weight = 1,
fillOpacity = 0.8,
group = "Fuera del polígono"
) %>%
# Agregar una leyenda para el estrato (solo para las casas dentro)
addLegend(
position = "bottomright",
pal = pal_estrato,
values = casas_norte_sf$estrato,
title = "Estrato",
opacity = 1
) %>%
# Agregar control de capas para alternar la visualización de ambos grupos
addLayersControl(
overlayGroups = c("Dentro del polígono", "Fuera del polígono"),
options = layersControlOptions(collapsed = FALSE)
)
n_fuera <- nrow(casas_norte_outside_sf)
cat("Se han encontrado", n_fuera, "viviendas que la data indicaba como Zona Norte, pero quedaron fuera del polígono.\n")
## Se han encontrado 212 viviendas que la data indicaba como Zona Norte, pero quedaron fuera del polígono.
En el gráfico “Precio vs Área Construida” se aprecia una tendencia positiva ya que a medida que aumenta el área construida (en metros cuadrados), el precio de la vivienda (en millones de pesos) también tiende a incrementarse. Aunque la dispersión de los puntos indica que no todo se explica únicamente por el área, sí se ve una correlación moderada: las viviendas con áreas superiores suelen presentar precios más elevados. Además, se observa que los estratos más altos (colores morado y verde en la leyenda) suelen concentrarse en precios mayores, reforzando la idea de que tanto el estrato como el área construida son factores relevantes en la determinación del valor.
Del mismo modo, en el gráfico “Precio vs Número de Baños” también se ve una relación positiva ya que a mayor cantidad de baños, tienden a aparecer precios más altos. Sin embargo, la dispersión es considerable y hay bastantes puntos con 2, 3 o 4 baños que se superponen en rangos de precio diversos. Esto sugiere que el número de baños influye en el precio, pero no de manera tan marcada como el área construida. Aun así, es coherente que inmuebles con más baños (generalmente asociados a mayor tamaño o confort) tengan precios más elevados.
Este gráfico muestra cómo, al pasar de estrato 3 a estrato 6, se observan aumentos claros en el precio de las viviendas. En estrato 3 predominan valores de 100 a 400 millones, mientras que en estrato 6 es frecuente ver precios por encima de 800 o 900 millones, llegando incluso a valores superiores a 1500 millones. La variable estrato, en Colombia, es un indicador socioeconómico de la ubicación y servicios de la vivienda, por lo que es esperable que viviendas en estratos más altos presenten mayores valores de mercado.
Finalmente el gráfico de cajas y bigotes permite observar la dispersión del precio en cada estrato y comparar la mediana, los cuartiles y los valores atípicos (outliers). Se destaca que en el estrato 3 la mediana del precio es relativamente baja (por debajo de 300 millones), aunque existen algunos outliers que superan los 600 millones. Para el estrato 4, la mediana sube (alrededor de 400-500 millones), con un rango más amplio y algunos puntos sobre 600 millones. En el estrato 5, los precios se incrementan, con medianas en torno a 700-800 millones y outliers que llegan a más de 1200 millones y el estrato 6, se aprecian los precios más altos, con medianas por encima de 900 millones y valores que superan ampliamente los 1500 millones.
Esta comparación deja en evidencia que estrato y precio guardan una fuerte relación y cada salto en estrato suele asociarse a un incremento notable en el precio.
# Extraer la data sin la geometría (ya que casas_norte_sf es un objeto sf)
df_zona <- st_drop_geometry(casas_norte_sf)
# Gráfico 1: Precio vs Área Construida
p1 <- plot_ly(df_zona,
x = ~areaconst,
y = ~preciom,
type = 'scatter',
mode = 'markers',
color = ~as.factor(estrato),
colors = 'Set1',
text = ~paste("<strong>Barrio:</strong>", barrio, "<br/>",
"<strong>Estrato:</strong>", estrato, "<br/>",
"<strong>Baños:</strong>", banios, "<br/>",
"<strong>Habitaciones:</strong>", habitaciones),
marker = list(size = 10)) %>%
layout(title = "Precio vs Área Construida (Zona Norte)",
xaxis = list(title = "Área Construida (m²)"),
yaxis = list(title = "Precio (millones de pesos)"))
p1
# Gráfico 2: Precio vs Número de Baños
p2 <- plot_ly(df_zona,
x = ~banios,
y = ~preciom,
type = 'scatter',
mode = 'markers',
color = ~as.factor(estrato),
colors = 'Set1',
text = ~paste(
"<strong>Barrio:</strong>", barrio, "<br/>",
"<strong>Área:</strong>", areaconst, "m²<br/>",
"<strong>Habitaciones:</strong>", habitaciones),
marker = list(size = 10)) %>%
layout(title = "Precio vs Número de Baños (Zona Norte)",
xaxis = list(title = "Número de Baños"),
yaxis = list(title = "Precio (millones de pesos)"))
p2
# Gráfico 3: Precio vs Número de Habitaciones
p3 <- plot_ly(df_zona,
x = ~habitaciones,
y = ~preciom,
type = 'scatter',
mode = 'markers',
color = ~as.factor(estrato),
colors = 'Set1',
text = ~paste(
"<strong>Barrio:</strong>", barrio, "<br/>",
"<strong>Área:</strong>", areaconst, "m²<br/>",
"<strong>Baños:</strong>", banios),
marker = list(size = 10)) %>%
layout(title = "Precio vs Número de Habitaciones (Zona Norte)",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio (millones de pesos)"))
# Gráfico 4: Precio vs Estrato
p4 <- plot_ly(df_zona,
x = ~estrato,
y = ~preciom,
type = 'scatter',
mode = 'markers',
color = ~as.factor(estrato),
colors = 'Set1',
text = ~paste(
"<strong>Barrio:</strong>", barrio, "<br/>",
"<strong>Área:</strong>", areaconst, "m²<br/>",
"<strong>Baños:</strong>", banios, "<br/>",
"<strong>Habitaciones:</strong>", habitaciones),
marker = list(size = 10)) %>%
layout(title = "Precio vs Estrato (Zona Norte)",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio (millones de pesos)"))
p4
# Gráfico 5: Distribución del Precio (boxplot)
p5 <- plot_ly(df_zona,
x = ~estrato,
y = ~preciom,
type = 'box',
color = ~as.factor(estrato),
colors = 'Set1') %>%
layout(title = "Distribución del Precio por Estrato (Zona Norte)",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio (millones de pesos)"))
p5
En primer lugar, se observa que la variable precio muestra la correlación más alta con el área construida (0.8437). Este valor positivo y cercano a 1 sugiere que, a medida que aumenta la superficie construida de la vivienda, el precio tiende a crecer de manera significativa. Asimismo, se aprecia una correlación de 0.6986 entre el precio y el estrato, lo que indica que la ubicación en un estrato socioeconómico más elevado suele estar asociada a un valor de mercado superior. Con el número de baños, la correlación es de 0.6385, también positiva y notoria, mientras que el número de habitaciones presenta un coeficiente de 0.4340, algo menor en comparación con las demás variables.
Por otro lado, entre las variables explicativas, el área construida (areaconst) y el número de baños (banios) exhiben un coeficiente de 0.6103, lo que sugiere que las viviendas más amplias tienden a contar con más baños. Igualmente, existe una correlación de 0.5929 entre el número de baños y el de habitaciones, reafirmando la idea de que los inmuebles con mayor número de cuartos suelen disponer de más baños. El número de habitaciones y el estrato, en cambio, presentan un valor de 0.1755, que es bastante bajo; esto significa que, en este conjunto de datos, disponer de más o menos cuartos no está fuertemente relacionado con pertenecer a un estrato alto o bajo.
En términos generales, se concluye que el precio de la vivienda en la Zona Norte depende de forma marcada de la combinación de factores como el área construida, el estrato y, en menor medida, el número de baños y habitaciones. La correlación más alta (precio–área) refuerza la idea de que el tamaño de la vivienda es un determinante clave en su valoración, seguido de la influencia del estrato. Este análisis numérico coincide con los hallazgos de la exploración gráfica previa y aporta evidencia cuantitativa sobre cómo interactúan las distintas características de la vivienda en la determinación de su precio. A continuación se aplica un análisis de correlación para identificar con exactitud las relaciones.
# Seleccionar las variables y eliminar NA
df_num <- df_zona %>%
select(preciom, areaconst, banios, habitaciones, estrato) %>%
na.omit()
# Calcular la matriz de correlación con el método de Spearman
cor_mat_spearman <- cor(df_num, method = "spearman")
# Crear una visualización interactiva de la matriz de correlación con plotly
plot_ly(
x = colnames(cor_mat_spearman),
y = rownames(cor_mat_spearman),
z = cor_mat_spearman,
type = "heatmap",
colors = colorRamp(c("blue", "white", "red"))
) %>%
layout(
title = "Matriz de Correlación",
xaxis = list(title = "Variables"),
yaxis = list(title = "Variables")
)
Analizando las correlaciones, en primer lugar, se observa que la variable precio muestra la correlación más alta con el área construida (0.8437). Este valor positivo y cercano a 1 sugiere que, a medida que aumenta la superficie construida de la vivienda, el precio tiende a crecer de manera significativa. Asimismo, se aprecia una correlación de 0.6986 entre el precio y el estrato, lo que indica que la ubicación en un estrato socioeconómico más elevado suele estar asociada a un valor de mercado superior. Con el número de baños, la correlación es de 0.6385, también positiva y notoria, mientras que el número de habitaciones presenta un coeficiente de 0.4340, algo menor en comparación con las demás variables.
Por otro lado, entre las variables explicativas, el área construida (areaconst) y el número de baños (banios) exhiben un coeficiente de 0.6103, lo que sugiere que las viviendas más amplias tienden a contar con más baños. Igualmente, existe una correlación de 0.5929 entre el número de baños y el de habitaciones, reafirmando la idea de que los inmuebles con mayor número de cuartos suelen disponer de más baños. El número de habitaciones y el estrato, en cambio, presentan un valor de 0.1755, que es bastante bajo; esto significa que, en este conjunto de datos, disponer de más o menos cuartos no está fuertemente relacionado con pertenecer a un estrato alto o bajo.
En términos generales, se concluye que el precio de la vivienda en la Zona Norte depende de forma marcada de la combinación de factores como el área construida, el estrato y, en menor medida, el número de baños y habitaciones. La correlación más alta (precio–área) refuerza la idea de que el tamaño de la vivienda es un determinante clave en su valoración, seguido de la influencia del estrato. Este análisis numérico coincide con los hallazgos de la exploración gráfica previa y aporta evidencia cuantitativa sobre cómo interactúan las distintas características de la vivienda en la determinación de su precio.
El modelo de regresión lineal múltiple se ha estimado con la variable respuesta, el precio de la vivienda (preciom), y con las siguientes variables explicativas: área construida (areaconst), estrato, número de habitaciones, número de parqueaderos y número de baños (banios). En este modelo, el precio se expresa como una función lineal de estas características, y los resultados obtenidos permiten evaluar la influencia de cada factor en el valor de mercado de la vivienda en la Zona Norte.
El coeficiente asociado al área construida es 0.6802 y resulta altamente significativo (p < 2e-16). Esto indica que, manteniendo constantes las demás variables, cada metro cuadrado adicional de construcción se asocia, en promedio, a un aumento en el precio de aproximadamente 0.68 millones de pesos. Del mismo modo el estrato, con un coeficiente de 82.52 y un p-valor muy significativo (p ≈ 3.93e-13), sugiere que, al pasar de un estrato a otro (por ejemplo, de 4 a 5), el precio aumenta en promedio en 82.52 millones de pesos.
Por otro lado, el número de habitaciones presenta un coeficiente de -7.38 que no es estadísticamente significativo (p = 0.230). Esto indica que, una vez controladas las otras variables, el número de habitaciones no tiene un efecto lineal claro sobre el precio de la vivienda. Es posible que su influencia ya se esté capturando a través del área construida o que la relación entre habitaciones y precio sea más compleja que la linealidad asumida en este modelo. En cuanto a los parqueaderos, el coeficiente es de 33.62 y es altamente significativo (p ≈ 5.60e-08), lo que significa que cada parqueadero adicional se asocia a un incremento de alrededor de 33.62 millones de pesos en el precio. Del mismo modo, el número de baños tiene un coeficiente de 22.81 (p ≈ 0.00778), indicando que cada baño adicional aumenta el precio en aproximadamente 22.81 millones de pesos.
El modelo presenta un R² de 0.6296 y un R² ajustado de 0.6245, lo que significa que aproximadamente el 62-63% de la variabilidad en el precio se explica por las variables incluidas. Esto indica un ajuste razonable, aunque queda un 37-38% de la variabilidad atribuible a otros factores no considerados en el modelo.
Los resultados son en gran parte lógicos y se alinean con las expectativas teóricas que el área construida y el estrato tienen efectos significativos y positivos sobre el precio, al igual que el número de parqueaderos y baños. La falta de significación en el coeficiente del número de habitaciones sugiere que este factor podría no tener una relación lineal directa o que su efecto ya esté reflejado en otra variable, como el área construida. Para mejorar el modelo, se podría considerar la inclusión de otras variables relevantes, la transformación de algunas (por ejemplo, aplicando logaritmos) o la incorporación de términos de interacción, lo que permitiría capturar mejor la complejidad del mercado inmobiliario.
# Estimar el modelo de regresión lineal múltiple
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = df_zona)
# Resumen del modelo
summary(modelo)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = df_zona)
##
## Residuals:
## Min 1Q Median 3Q Max
## -697.25 -80.60 -16.54 50.26 695.21
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -210.8233 48.4688 -4.350 1.77e-05 ***
## areaconst 0.6802 0.0549 12.391 < 2e-16 ***
## estrato 82.5199 10.9561 7.532 3.93e-13 ***
## habitaciones -7.3822 6.1434 -1.202 0.23028
## parqueaderos 33.6156 6.0612 5.546 5.60e-08 ***
## banios 22.8105 8.5237 2.676 0.00778 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 155.3 on 367 degrees of freedom
## (186 observations deleted due to missingness)
## Multiple R-squared: 0.6296, Adjusted R-squared: 0.6245
## F-statistic: 124.7 on 5 and 367 DF, p-value: < 2.2e-16
El conjunto de gráficos diagnósticos permite evaluar si se cumplen los principales supuestos de la regresión lineal múltiple. En la gráfica de residuos frente a valores ajustados se observa que los puntos se dispersan de forma relativamente aleatoria alrededor de la línea horizontal, por lo que la relación entre las variables explicativas y la variable respuesta no presenta desviaciones graves de la linealidad. Sin embargo, en los valores ajustados más altos, la dispersión de los residuos aumenta, lo que podría indicar un leve problema de heteroscedasticidad. El Q-Q plot muestra que la mayoría de los residuos se alinean cerca de la diagonal de referencia, lo que respalda la suposición de normalidad, aunque en las colas aparecen algunas desviaciones que no parecen lo suficientemente marcadas como para invalidar el análisis. El gráfico Scale-Location (o √|residuos| frente a los valores ajustados) confirma en parte la sospecha de varianza creciente, ya que la línea roja muestra una pendiente ascendente; no obstante, el patrón no es tan pronunciado como para sugerir una heteroscedasticidad severa. La gráfica de residuos contra leverage, complementada por la distancia de Cook, revela que algunos puntos (identificados con sus respectivos índices) podrían estar ejerciendo influencia notable en la estimación de los coeficientes. Estos casos, en general, merecen una inspección individual para determinar si corresponden a valores atípicos genuinos o a posibles errores de registro: además, la prueba de Durbin-Watson arroja un estadístico cercano a 2, lo que en principio descarta la presencia de una fuerte autocorrelación en los errores. En conjunto, los resultados indican que el modelo cumple de forma razonable los supuestos de linealidad, normalidad y homoscedasticidad, aunque sería conveniente vigilar la leve tendencia a la varianza creciente y revisar las observaciones potencialmente influyentes por lo que la prueba de Durbin-Watson y los gráficos de influencia refuerzan la necesidad de vigilar la posible autocorrelación y el impacto de outliers, sin que ello implique, por ahora, un incumplimiento grave de los supuestos del modelo.
vivienda1_escenarios <- data.frame(
areaconst = c(200, 200),
estrato = c(4, 5),
habitaciones = c(4, 4),
parqueaderos = c(1, 1),
banios = c(2, 2)
)
predict(modelo, newdata = vivienda1_escenarios)
## 1 2
## 305.0033 387.5232
El modelo de regresión estima que para una vivienda en la Zona Norte con 200 m² de área construida, 4 habitaciones, 1 parqueadero y 2 baños, el precio varía significativamente según el estrato. En el escenario en el que la vivienda se clasifica como estrato 4, la predicción indica un valor aproximado de 305 millones de pesos. Por el contrario, si la vivienda se clasifica en estrato 5, el precio estimado asciende a unos 388 millones de pesos.
Estos resultados subrayan la fuerte influencia del estrato en la valoración del inmueble. Con un crédito preaprobado de 350 millones de pesos, únicamente el escenario de estrato 4 se ajustaría a dicho monto, mientras que la clasificación en estrato 5 implicaría un sobrecosto que requeriría recursos adicionales o una renegociación en las condiciones de financiamiento. La diferencia en la predicción refuerza la importancia de contar con una clasificación precisa del estrato para la valoración y toma de decisiones en el mercado inmobiliario.
Se encontró únicamente una propiedad que cumple los criterios exactos de la Vivienda 1, es decir, una casa ubicada en la zona norte con al menos 200 m² de área construida, un parqueadero, dos baños, cuatro habitaciones, estrato 4 o 5 y un precio no mayor a 350 millones. La oferta identificada se localiza en el barrio Vipasa, con un precio de 350 millones, un área construida de 346 m², un parqueadero, dos baños, cuatro habitaciones y estrato 5. Estas características la convierten en la única opción estrictamente alineada con la solicitud del cliente, dentro de la base de datos analizada. Sin embargo, si se aplican los criterios de forma más flexible, de modo que el inmueble cuente con al menos 200 m² de área construida, 1 o más parqueaderos, 2 o más baños, 4 o más habitaciones, estrato 4 o 5 y un precio igual o inferior a 350 millones, se identifican 30 viviendas disponibles en la Zona Norte. Estas propiedades se representan en el mapa, donde cada punto corresponde a una oferta que cumple con las condiciones mencionadas. Al hacer clic en un marcador, se despliega un popup con información detallada de la vivienda, como el barrio, precio, área construida, número de parqueaderos, baños y habitaciones, así como el estrato. Esta visualización facilita la comparación de ofertas y la evaluación de aquellas que se ajusten mejor a las preferencias del cliente.
strict_matches <- casas_norte_sf %>%
filter(
tipo == "Casa", # Debe ser casa
areaconst >= 200, # Área construida exactamente 200 m²
parqueaderos >= 1, # Exactamente 1 parqueadero
banios >= 2, # Exactamente 2 baños
habitaciones >= 4, # Exactamente 4 habitaciones
estrato %in% c(4, 5), # Estrato 4 o 5
preciom <= 350 # Precio menor o igual a 350 millones
)
leaflet(data = strict_matches) %>%
addTiles() %>%
# Agregar el polígono de la Zona Norte
addPolygons(data = zonaNorte_sfc,
fillColor = "blue",
fillOpacity = 0.1,
color = "blue",
weight = 2,
popup = "Zona Norte") %>%
# Agregar marcadores para las ofertas potenciales
addCircleMarkers(
popup = ~paste(
"<strong>Barrio:</strong>", barrio, "<br/>",
"<strong>Precio:</strong>", preciom, " millones<br/>",
"<strong>Área construida:</strong>", areaconst, " m²<br/>",
"<strong>Parqueaderos:</strong>", parqueaderos, "<br/>",
"<strong>Baños:</strong>", banios, "<br/>",
"<strong>Habitaciones:</strong>", habitaciones, "<br/>",
"<strong>Estrato:</strong>", estrato
),
radius = 5,
fillColor = "green",
color = "white",
weight = 1,
fillOpacity = 0.8
) %>%
addLegend(position = "bottomright",
colors = "green",
labels = "Oferta Potencial",
title = "Ofertas")