La compañía C&A (Casas y Apartamentos), fundada por María en la ciudad de Cali, recibió una solicitud de una empresa internacional que requiere adquirir dos viviendas para reubicar a dos de sus empleados con sus familias. En el presente informe que tiene como objetivo analizar el mercado inmobiliario de Cali mediante técnicas de modelación estadística; específicamente, la regresión lineal múltiple, para estimar el precio de las viviendas solicitadas y recomendar ofertas concretas que se ajusten a los requerimientos y al presupuesto disponible.
Las dos viviendas solicitadas presentan las siguientes especificaciones:
Característica Vivienda 1
Vivienda 2
Tipo Casa Apartamento
Área construida (m²) 200 300
Parqueaderos 1 3
Baños 2 3
Habitaciones 4 5
Estrato 4 o 5 5 o 6
Zona Norte Sur
Crédito preaprobado $350 millones COP $850 millones COP
Los análisis se estructuran en dos secciones principales, una por cada vivienda, y cada sección sigue una secuencia: filtrado de datos, análisis exploratorio, modelación, validación de supuestos, predicción y recomendación de ofertas que se presentan a continuación.
library(paqueteMODELOS)
library(tidyverse)
library(plotly)
library(leaflet)
library(DT)
library(lmtest)
library(nortest)
library(car)
library(kableExtra)
library(broom)
data("vivienda")La base de datos contiene registros de ofertas inmobiliarias en la ciudad de Cali, con 13 variables que incluyen ubicación geográfica (zona, barrio, coordenadas), características físicas (área construida, habitaciones, baños, parqueaderos, piso), estratificación socioeconómica, tipo de vivienda y precio en millones de pesos colombianos.
## Rows: 8,322
## Columns: 13
## $ id <dbl> 1147, 1169, 1350, 5992, 1212, 1724, 2326, 4386, 1209, 159…
## $ zona <chr> "Zona Oriente", "Zona Oriente", "Zona Oriente", "Zona Sur…
## $ piso <chr> NA, NA, NA, "02", "01", "01", "01", "01", "02", "02", "02…
## $ estrato <dbl> 3, 3, 3, 4, 5, 5, 4, 5, 5, 5, 6, 4, 5, 6, 4, 5, 5, 4, 5, …
## $ preciom <dbl> 250, 320, 350, 400, 260, 240, 220, 310, 320, 780, 750, 62…
## $ areaconst <dbl> 70, 120, 220, 280, 90, 87, 52, 137, 150, 380, 445, 355, 2…
## $ parqueaderos <dbl> 1, 1, 2, 3, 1, 1, 2, 2, 2, 2, NA, 3, 2, 2, 1, 4, 2, 2, 2,…
## $ banios <dbl> 3, 2, 2, 5, 2, 3, 2, 3, 4, 3, 7, 5, 6, 2, 4, 4, 4, 3, 2, …
## $ habitaciones <dbl> 6, 3, 4, 3, 3, 3, 3, 4, 6, 3, 6, 5, 6, 2, 5, 5, 4, 3, 3, …
## $ tipo <chr> "Casa", "Casa", "Casa", "Casa", "Apartamento", "Apartamen…
## $ barrio <chr> "20 de julio", "20 de julio", "20 de julio", "3 de julio"…
## $ longitud <dbl> -76.51168, -76.51237, -76.51537, -76.54000, -76.51350, -7…
## $ latitud <dbl> 3.43382, 3.43369, 3.43566, 3.43500, 3.45891, 3.36971, 3.4…
Primero, se filtra la base para conservar únicamente las ofertas de las casas ubicadas en la Zona Norte de Cali:
El subconjunto resultante contiene 722 registros. A continuación se presentan los primeros tres registros y las tablas de verificación que confirman la correcta aplicación del filtro.
base1 %>%
head(3) %>%
kable(caption = "Primeros 3 registros — Casas Zona Norte") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| 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 |
table(base1$tipo) %>%
kable(col.names = c("Tipo", "Frecuencia"),
caption = "Verificación: solo tipo Casa") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Tipo | Frecuencia |
|---|---|
| Casa | 722 |
table(base1$zona) %>%
kable(col.names = c("Zona", "Frecuencia"),
caption = "Verificación: solo Zona Norte") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Zona | Frecuencia |
|---|---|
| Zona Norte | 722 |
table(base1$estrato) %>%
kable(col.names = c("Estrato", "Frecuencia"),
caption = "Distribución por estrato de las Casas Zona Norte") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Estrato | Frecuencia |
|---|---|
| 3 | 235 |
| 4 | 161 |
| 5 | 271 |
| 6 | 55 |
Como se observa que la distribución por estrato se concentra principalmente en los estratos 3 (n = 235) y 5 (n = 271), seguidos por el estrato 4 (n = 161) y el estrato 6 (n = 55). Esta distribución es coherente con la composición socioeconómica de los barrios del norte de Cali, donde conviven sectores residenciales de estratos medios y altos.
leaflet(base1) %>%
addTiles() %>%
addCircleMarkers(
~longitud, ~latitud,
radius = 4, color = "steelblue", fillOpacity = 0.6,
popup = ~paste0(
"<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio:</b> $", preciom, " M<br>",
"<b>Área:</b> ", areaconst, " m²<br>",
"<b>Estrato:</b> ", estrato
)
) %>%
addLegend("bottomright", colors = "steelblue", labels = "Casas Zona Norte")Al inspeccionar el mapa, se puede observar que la gran mayoría de los puntos se concentran efectivamente en la zona norte de Cali en barrios como Acopi, Vipasa, Flora, San Vicente, entre otros. Sin embargo, algunos registros presentan coordenadas que los ubican en zonas aparentemente más centrales o incluso al sur de la ciudad. Esto puede deberse a varias razones: priemro, la categorización de “Zona Norte” en la base de datos obedece a criterios de la fuente inmobiliaria, que no necesariamente coinciden con la delimitación geográfica oficial del Plan de Ordenamiento Territorial (POT) de Cali; segundo, se puede deber a posibles errores de geocodificación en las coordenadas de latitud y longitud; o tercero, los barrios cuya clasificación zonal es ambigua por encontrarse en zonas limítrofes. Para un análisis más detallado convendría contrastar las coordenadas con los polígonos oficiales de las comunas de Cali.
## preciom areaconst estrato banios
## Min. : 89.0 Min. : 30.0 Min. :3.000 Min. : 0.000
## 1st Qu.: 261.2 1st Qu.: 140.0 1st Qu.:3.000 1st Qu.: 2.000
## Median : 390.0 Median : 240.0 Median :4.000 Median : 3.000
## Mean : 445.9 Mean : 264.9 Mean :4.202 Mean : 3.555
## 3rd Qu.: 550.0 3rd Qu.: 336.8 3rd Qu.:5.000 3rd Qu.: 4.000
## Max. :1940.0 Max. :1440.0 Max. :6.000 Max. :10.000
##
## habitaciones parqueaderos
## Min. : 0.000 Min. : 1.000
## 1st Qu.: 3.000 1st Qu.: 1.000
## Median : 4.000 Median : 2.000
## Mean : 4.507 Mean : 2.182
## 3rd Qu.: 5.000 3rd Qu.: 3.000
## Max. :10.000 Max. :10.000
## NA's :287
Las casas de la Zona Norte presentan un precio promedio de $445.9
millones, con una mediana de $390 millones, lo que indica asimetría
positiva en la distribución, un rango que va desde $89 millones hasta
$1.940 millones. El área construida promedio es de 264.9 m² (mediana:
240 m²), considerablemente mayor que la del mercado general, lo cual es
consistente con la tipología de casas. Se observa que la variable
parqueaderos presenta 287 valores faltantes (39.8% de la
base), lo que reducirá el tamaño efectivo de la muestra en la estimación
del modelo.
plot_ly(base1, x = ~preciom, type = "histogram", nbinsx = 30,
marker = list(color = "steelblue",
line = list(color = "white", width = 0.5))) %>%
layout(title = "Distribución del precio — Casas Zona Norte",
xaxis = list(title = "Precio (millones COP)"),
yaxis = list(title = "Frecuencia"))La distribución del precio muestra una marcada asimetría positiva (sesgo a la derecha), con la mayor concentración de ofertas en el rango de $200 a $550 millones y una cola larga hacia valores superiores a $1.000 millones.
plot_ly(base1, x = ~areaconst, y = ~preciom, color = ~factor(estrato),
type = "scatter", mode = "markers",
text = ~paste("Barrio:", barrio, "<br>Estrato:", estrato,
"<br>Baños:", banios, "<br>Hab:", habitaciones),
hoverinfo = "text+x+y",
marker = list(size = 7, opacity = 0.7)) %>%
layout(title = "Precio vs. Área construida (por estrato)",
xaxis = list(title = "Área construida (m²)"),
yaxis = list(title = "Precio (millones COP)"),
legend = list(title = list(text = "Estrato")))El gráfico de dispersión revela una relación positiva clara entre el área construida y el precio; es decir, a mayor área, mayor precio. Adicionalmente, se aprecia un efecto de segmentación por estrato donde las observaciones de estratos 5 y 6 tienden a ubicarse en la parte superior de la nube de puntos (precios más altos para un área similar), mientras que las de estrato 3 se concentran en la parte inferior. Esto sugiere que el estrato captura información adicional sobre la valorización del inmueble más allá del tamaño físico, como la calidad del entorno y los acabados esperados.
plot_ly(base1, x = ~factor(estrato), y = ~preciom, type = "box",
color = ~factor(estrato),
colors = c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728")) %>%
layout(title = "Distribución del precio por estrato — Casas Zona Norte",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio (millones COP)"),
showlegend = FALSE)Se observa un incremento progresivo en la mediana del precio conforme aumenta el estrato donde las casas de estrato 6 presentan medianas y rangos intercuartílicos notablemente superiores. El estrato 3 concentra sus valores alrededor de $200–$350 millones, mientras que el estrato 6 supera frecuentemente los $600 millones y en todos los estratos se detectan outliers superiores, indicando casas con precios atípicamente altos.
plot_ly(base1, x = ~factor(banios), y = ~preciom, type = "box",
color = ~factor(banios)) %>%
layout(title = "Precio por número de baños",
xaxis = list(title = "Número de baños"),
yaxis = list(title = "Precio (millones COP)"),
showlegend = FALSE)El número de baños presenta una tendencia ascendente en relación con el precio, especialmente a partir de 4 baños. No obstante, la alta variabilidad observada en las categorías superiores (6+ baños) se debe probablemente a un tamaño muestral reducido en esos niveles.
plot_ly(base1, x = ~factor(habitaciones), y = ~preciom, type = "box",
color = ~factor(habitaciones)) %>%
layout(title = "Precio por número de habitaciones",
xaxis = list(title = "Número de habitaciones"),
yaxis = list(title = "Precio (millones COP)"),
showlegend = FALSE)La relación entre el número de habitaciones y el precio es positiva pero menos pronunciada que la del área o el estrato, lo cual es lógico puesto que las habitaciones están correlacionadas con el área construida (a mayor área, más habitaciones).
vars_num1 <- base1 %>%
select(preciom, areaconst, estrato, banios, habitaciones, parqueaderos)
cor_mat1 <- cor(vars_num1, use = "complete.obs")
plot_ly(
x = colnames(cor_mat1), y = colnames(cor_mat1),
z = cor_mat1, type = "heatmap",
colorscale = "RdBu", zmin = -1, zmax = 1,
text = round(cor_mat1, 2), hoverinfo = "text"
) %>%
layout(title = "Matriz de correlación — Casas Zona Norte",
xaxis = list(tickangle = -45))La matriz de correlación confirma lo observado gráficamente:
Con base en los análisis annteriores, se propone un modelo de regresión lineal múltiple con el precio como variable dependiente y cinco variables predictoras:
\[\text{preciom} = \beta_0 + \beta_1 \cdot \text{areaconst} + \beta_2 \cdot \text{estrato} + \beta_3 \cdot \text{habitaciones} + \beta_4 \cdot \text{parqueaderos} + \beta_5 \cdot \text{banios} + \varepsilon\]
modelo1 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios,
data = base1)
summary(modelo1)##
## 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
tidy(modelo1, conf.int = TRUE) %>%
mutate(across(where(is.numeric), ~round(., 4))) %>%
kable(caption = "Coeficientes estimados — Modelo 1 (Casas Zona Norte)",
col.names = c("Variable", "Estimación", "Error Estándar",
"Estadístico t", "p-valor", "IC 95% Inf.", "IC 95% Sup.")) %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| Variable | Estimación | Error Estándar | Estadístico t | p-valor | IC 95% Inf. | IC 95% Sup. |
|---|---|---|---|---|---|---|
| (Intercept) | -238.1709 | 44.4055 | -5.3635 | 0.0000 | -325.4503 | -150.8915 |
| areaconst | 0.6767 | 0.0528 | 12.8140 | 0.0000 | 0.5729 | 0.7805 |
| estrato | 80.6349 | 9.8263 | 8.2060 | 0.0000 | 61.3212 | 99.9487 |
| habitaciones | 7.6451 | 5.6587 | 1.3510 | 0.1774 | -3.4772 | 18.7674 |
| parqueaderos | 24.0060 | 5.8689 | 4.0904 | 0.0001 | 12.4706 | 35.5413 |
| banios | 18.8994 | 7.4880 | 2.5240 | 0.0120 | 4.1816 | 33.6171 |
Con base en los resultados del modelo, se presentan las siguientes interpretaciones respecto al mercado inmobiliario de Cali:
Intercepto (β₀ = –238.17, p < 0.001): el valor teórico del precio cuando todas las variables predictoras son cero resulta negativo, lo cual carece de sentido práctico pero es algebraicamente necesario para el ajuste del hiperplano de regresión.
Área construida (β₁ = 0.677, p < 0.001): por cada metro cuadrado adicional de área construida, el precio de la casa se incrementa en aproximadamente $0.68 millones (≈ $677.000 COP), manteniendo las demás variables constantes. Este resultado es altamente significativo y coherente con la lógica del mercado donde el tamaño de la propiedad es uno de los principales determinantes del valor.
Estrato (β₂ = 80.63, p < 0.001): cada incremento de un nivel de estrato se asocia con un aumento promedio de $80.6 millones en el precio. Es el segundo predictor con mayor impacto, lo cual refleja que el estrato en Colombia no solo captura la ubicación geográfica, sino también la calidad del entorno urbano, los servicios públicos y la valorización percibida del sector.
Habitaciones (β₃ = 7.65, p = 0.177): el coeficiente de habitaciones no es estadísticamente significativo al nivel convencional de α = 0.05. Esto puede explicarse por su colinealidad con el área construida; es decir, una vez controlado el efecto del tamaño de la casa, el número de habitaciones no aporta información adicional significativa para explicar el precio.
Parqueaderos (β₄ = 24.01, p < 0.001): cada parqueadero adicional incrementa el precio en aproximadamente $24 millones. Este efecto es razonable, ya que los parqueaderos privados constituyen un atributo altamente valorado en el mercado inmobiliario colombiano, especialmente en zonas residenciales urbanas.
Baños (β₅ = 18.90, p = 0.012): cada baño adicional se asocia con un incremento de $18.9 millones en el precio. El efecto es estadísticamente significativo al nivel del 5%, aunque con menor potencia que el área o el estrato.
r2_1 <- summary(modelo1)$r.squared
r2_adj_1 <- summary(modelo1)$adj.r.squared
data.frame(
Métrica = c("R²", "R² ajustado", "Error estándar residual", "Observaciones utilizadas"),
Valor = c(round(r2_1, 4), round(r2_adj_1, 4), "155.1 millones", "435 (de 722)")
) %>%
kable(caption = "Indicadores de ajuste del Modelo 1") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Métrica | Valor |
|---|---|
| R² | 0.6041 |
| R² ajustado | 0.5995 |
| Error estándar residual | 155.1 millones |
| Observaciones utilizadas | 435 (de 722) |
El modelo explica el 60.4% de la variabilidad del precio de las casas en la Zona Norte (R² = 0.6041; R² ajustado = 0.5995). Si bien este nivel de ajuste es moderado, es aceptable para un modelo de regresión con datos de mercado inmobiliario, donde factores no observados —como la antigüedad de la construcción, la calidad de los acabados, la cercanía a vías principales y centros comerciales— influyen significativamente en el precio.
Es importante señalar que 287 observaciones fueron excluidas del
ajuste por datos faltantes en la variable parqueaderos, lo
que redujo la muestra efectiva a 435 registros.
Los gráficos diagnósticos revelan, primero, en el gráfico de residuos vs. valores ajustados se observa un patrón en forma de embudo (varianza creciente), indicativo de heterocedasticidad; segundo, el Q-Q plot muestra desviaciones pronunciadas en ambas colas, señalando no normalidad de los residuos; tercero, el gráfico de distancia de Cook identifica algunas observaciones influyentes que podrían estar afectando la estimación.
##
## Shapiro-Wilk normality test
##
## data: residuals(modelo1)
## W = 0.85246, p-value < 2.2e-16
qq_data1 <- data.frame(
teorico = qqnorm(residuals(modelo1), plot.it = FALSE)$x,
muestral = qqnorm(residuals(modelo1), plot.it = FALSE)$y
)
plot_ly(qq_data1, x = ~teorico, y = ~muestral,
type = "scatter", mode = "markers",
marker = list(color = "steelblue", size = 4, opacity = 0.6)) %>%
add_trace(x = c(-4, 4), y = c(-4 * sd(residuals(modelo1)), 4 * sd(residuals(modelo1))),
type = "scatter", mode = "lines",
line = list(color = "red", dash = "dash"),
name = "Referencia") %>%
layout(title = "Q-Q Plot de residuos — Modelo 1",
xaxis = list(title = "Cuantiles teóricos"),
yaxis = list(title = "Cuantiles muestrales"),
showlegend = FALSE)El test de Shapiro-Wilk arrojó un estadístico W = 0.8525 con p-valor < 2.2 × 10⁻¹⁶, lo cual rechaza de manera contundente la hipótesis nula de normalidad. El Q-Q plot interactivo confirma que los residuos se desvían de la distribución normal, particularmente en las colas (colas pesadas a la derecha), consistente con la asimetría positiva del precio.
##
## studentized Breusch-Pagan test
##
## data: modelo1
## BP = 80.281, df = 5, p-value = 7.33e-16
El test de Breusch-Pagan resultó altamente significativo (BP = 80.28, df = 5, p = 7.33 × 10⁻¹⁶), lo que implicó el rechazo de la hipótesis de varianza constante. Esto confirmó lo observado gráficamente; es decir, la dispersión de los residuos aumenta con el valor ajustado (casas más caras tienen errores de predicción más variables).
##
## Durbin-Watson test
##
## data: modelo1
## DW = 1.7615, p-value = 0.005472
## alternative hypothesis: true autocorrelation is greater than 0
El test de Durbin-Watson arrojó un valor DW = 1.76 con p = 0.005, lo cual indicó evidencia leve de autocorrelación positiva en los residuos. Si bien el estadístico se aleja moderadamente de 2, esta desviación puede deberse a la estructura espacial de los datos (propiedades cercanas geográficamente tienden a tener precios similares) más que a una verdadera dependencia temporal.
vif_df1 <- vif(modelo1) %>%
as.data.frame() %>%
rownames_to_column("Variable")
names(vif_df1)[2] <- "VIF"
vif_df1 %>%
mutate(VIF = round(VIF, 3),
Diagnóstico = ifelse(VIF < 5, "Aceptable", "Problemático")) %>%
kable(caption = "Factores de Inflación de Varianza (VIF) — Modelo 1") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Variable | VIF | Diagnóstico |
|---|---|---|
| areaconst | 1.461 | Aceptable |
| estrato | 1.308 | Aceptable |
| habitaciones | 1.721 | Aceptable |
| parqueaderos | 1.226 | Aceptable |
| banios | 1.967 | Aceptable |
Todos los valores de VIF son inferiores a 2, muy por debajo del
umbral crítico convencional de 5 (o del más conservador de 10). Esto
indica que no existe multicolinealidad problemática entre los
predictores del modelo, lo cual garantiza estabilidad en la estimación
de los coeficientes individuales. El valor más alto corresponde a
banios (VIF ≈ 1.97), seguido de habitaciones
(VIF ≈ 1.72), lo cual es esperado dado que ambas variables se
correlacionan con el tamaño de la vivienda.
Supuesto Test / Método
Resultado Conclusión Normalidad
Shapiro-Wilk W = 0.852, p < 0.001 Violado
Homocedasticidad Breusch-Pagan BP = 80.28, p < 0.001
Violado
Independencia Durbin-Watson DW = 1.76, p = 0.005 Levemente
violado
No multicolinealidad VIF Todos < 2.0 Cumple
Nota: a pesar de las violaciones identificadas, el modelo se utiliza con fines exploratorios y de predicción puntual. Las violaciones de normalidad y homocedasticidad afectan principalmente la precisión de los intervalos de confianza y las pruebas de hipótesis, pero no invalidan la capacidad predictiva del modelo.
Se realiza la predicción del precio para una casa con las características solicitadas. Dado que el enunciado indica estrato “4 o 5”, se presentan ambos escenarios:
vivienda1_e4 <- data.frame(areaconst = 200, estrato = 4,
habitaciones = 4, parqueaderos = 1, banios = 2)
vivienda1_e5 <- data.frame(areaconst = 200, estrato = 5,
habitaciones = 4, parqueaderos = 1, banios = 2)
pred1_e4 <- predict(modelo1, newdata = vivienda1_e4, interval = "prediction", level = 0.95)
pred1_e5 <- predict(modelo1, newdata = vivienda1_e5, interval = "prediction", level = 0.95)
rbind(
data.frame(Escenario = "Estrato 4", round(as.data.frame(pred1_e4), 2)),
data.frame(Escenario = "Estrato 5", round(as.data.frame(pred1_e5), 2))
) %>%
rename("Predicción (M COP)" = fit,
"Lím. Inferior 95%" = lwr,
"Lím. Superior 95%" = upr) %>%
kable(caption = "Predicción del precio — Vivienda 1") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| Escenario | Predicción (M COP) | Lím. Inferior 95% | Lím. Superior 95% | |
|---|---|---|---|---|
| 1 | Estrato 4 | 312.10 | 6.21 | 618.00 |
| 11 | Estrato 5 | 392.74 | 86.20 | 699.28 |
Análisis de las predicciones:
Estrato 4: el precio estimado es de $312.1 millones (IC 95%: $6.2 – $618.0 millones). Esta predicción se sitúa dentro del presupuesto de $350 millones, lo cual indica que la empresa tendría margen financiero para adquirir una casa de estas características en estrato 4.
Estrato 5: el precio estimado asciende a $392.7 millones (IC 95%: $86.2 – $699.3 millones). Esta predicción supera el crédito preaprobado de $350 millones, lo que sugiere que la búsqueda en estrato 5 podría requerir negociación o la consideración de viviendas de menor área.
La amplitud de los intervalos de predicción (≈ $610 millones) refleja la alta variabilidad no explicada por el modelo (R² = 0.60) y las violaciones de supuestos identificadas.
Se filtran las ofertas disponibles que satisfacen las condiciones de la solicitud (casas en zona norte, estrato 4 o 5, ≥ 3 habitaciones, ≥ 2 baños, ≥ 1 parqueadero) y cuyo precio no supere el crédito preaprobado de $350 millones:
ofertas1 <- base1 %>%
filter(
preciom <= 350,
estrato %in% c(4, 5),
habitaciones >= 3,
banios >= 2,
parqueaderos >= 1
) %>%
arrange(desc(areaconst))
cat("Total de ofertas que cumplen las condiciones:", nrow(ofertas1))## Total de ofertas que cumplen las condiciones: 81
top5_ofertas1 <- ofertas1 %>% head(5)
top5_ofertas1 %>%
select(barrio, preciom, areaconst, estrato, habitaciones, banios, parqueaderos) %>%
mutate(
`Precio/m²` = round(preciom / areaconst, 2)
) %>%
kable(caption = "Top 5 ofertas recomendadas — Vivienda 1 (≤ $350M)",
col.names = c("Barrio", "Precio (M)", "Área (m²)", "Estrato",
"Hab.", "Baños", "Parq.", "Precio/m² (M)")) %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| Barrio | Precio (M) | Área (m²) | Estrato | Hab. | Baños | Parq. | Precio/m² (M) |
|---|---|---|---|---|---|---|---|
| san vicente | 340 | 355 | 5 | 8 | 5 | 2 | 0.96 |
| salomia | 350 | 350 | 4 | 5 | 4 | 1 | 1.00 |
| vipasa | 350 | 346 | 5 | 4 | 2 | 1 | 1.01 |
| el bosque | 350 | 300 | 5 | 6 | 5 | 3 | 1.17 |
| el bosque | 335 | 300 | 4 | 4 | 4 | 3 | 1.12 |
leaflet(top5_ofertas1) %>%
addTiles() %>%
addCircleMarkers(
~longitud, ~latitud,
radius = 9, color = "red", fillOpacity = 0.85,
popup = ~paste0(
"<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio:</b> $", preciom, " M<br>",
"<b>Área:</b> ", areaconst, " m²<br>",
"<b>Estrato:</b> ", estrato, "<br>",
"<b>Hab:</b> ", habitaciones, " | <b>Baños:</b> ", banios,
" | <b>Parq:</b> ", parqueaderos
),
label = ~paste0("$", preciom, "M — ", barrio)
) %>%
addLegend("bottomright", colors = "red", labels = "Ofertas recomendadas")Discusión de las ofertas:
Las cinco ofertas seleccionadas ofrecen áreas construidas entre 300 y 355 m² —superiores a los 200 m² requeridos—, lo cual representa una ventaja significativa para la empresa solicitante. Se destacan las siguientes observaciones:
San Vicente ($340M, 355 m², estrato 5): la mejor relación precio/m² y la mayor área construida. Es la oferta más destacada, con 8 habitaciones y 5 baños, superando ampliamente las necesidades mínimas.
Salomia ($350M, 350 m², estrato 4): área similar a la anterior a un precio que coincide con el tope presupuestal. Ofrece 5 habitaciones y 4 baños.
Vipasa ($350M, 346 m², estrato 5): en estrato 5 con un área generosa, aunque solo 2 baños (el mínimo requerido).
El Bosque ($350M, 300 m², estrato 5 y $335M, 300 m², estrato 4): dos opciones en el mismo barrio que ofrecen buen espacio con diferencia de estrato y precio.
La oferta de San Vicente constituye la opción más competitiva en términos de relación costo-beneficio, seguida por la de Salomia. Se sugiere a María programar visitas de inspección y verificar el estado de conservación de estas propiedades.
El subconjunto de apartamentos en la Zona Sur contiene 2787 registros, una muestra significativamente mayor que la de casas en zona norte, lo cual favorecerá la estabilidad de las estimaciones.
base2 %>%
head(3) %>%
kable(caption = "Primeros 3 registros — Apartamentos Zona Sur") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| 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 |
table(base2$tipo) %>%
kable(col.names = c("Tipo", "Frecuencia"),
caption = "Verificación: solo tipo Apartamento") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Tipo | Frecuencia |
|---|---|
| Apartamento | 2787 |
table(base2$zona) %>%
kable(col.names = c("Zona", "Frecuencia"),
caption = "Verificación: solo Zona Sur") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Zona | Frecuencia |
|---|---|
| Zona Sur | 2787 |
table(base2$estrato) %>%
kable(col.names = c("Estrato", "Frecuencia"),
caption = "Distribución por estrato — Apartamentos Zona Sur") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Estrato | Frecuencia |
|---|---|
| 3 | 201 |
| 4 | 1091 |
| 5 | 1033 |
| 6 | 462 |
La distribución por estrato muestra una concentración en los estratos 4 (n = 1.091, 39.1%) y 5 (n = 1.033, 37.1%), seguidos del estrato 6 (n = 462, 16.6%) y el estrato 3 (n = 201, 7.2%). La Zona Sur de Cali alberga barrios de alta valorización como El Ingenio, Ciudad Jardín, Valle del Lili y Caney, lo que explica el predominio de estratos medios-altos.
leaflet(base2) %>%
addTiles() %>%
addCircleMarkers(
~longitud, ~latitud,
radius = 3, color = "darkgreen", fillOpacity = 0.5,
popup = ~paste0(
"<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio:</b> $", preciom, " M<br>",
"<b>Área:</b> ", areaconst, " m²<br>",
"<b>Estrato:</b> ", estrato
)
) %>%
addLegend("bottomright", colors = "darkgreen", labels = "Apartamentos Zona Sur")La mayoría de los registros se concentra en la franja sur-occidental de Cali, como es esperado. De manera similar al caso anterior, se observan algunos puntos dispersos que podrían ubicarse fuera de los límites convencionales de la Zona Sur. Las razones son análogas: discrepancias entre la clasificación de la fuente de datos inmobiliarios y los límites oficiales del POT, o errores en la geocodificación. En un contexto aplicado, estas discrepancias se subsanan mediante verificación directa de las direcciones.
## preciom areaconst estrato banios
## Min. : 75.0 Min. : 40.00 Min. :3.00 Min. :0.000
## 1st Qu.: 175.0 1st Qu.: 65.00 1st Qu.:4.00 1st Qu.:2.000
## Median : 245.0 Median : 85.00 Median :5.00 Median :2.000
## Mean : 297.3 Mean : 97.47 Mean :4.63 Mean :2.488
## 3rd Qu.: 335.0 3rd Qu.:110.00 3rd Qu.:5.00 3rd Qu.:3.000
## Max. :1750.0 Max. :932.00 Max. :6.00 Max. :8.000
##
## habitaciones parqueaderos
## Min. :0.000 Min. : 1.000
## 1st Qu.:3.000 1st Qu.: 1.000
## Median :3.000 Median : 1.000
## Mean :2.966 Mean : 1.415
## 3rd Qu.:3.000 3rd Qu.: 2.000
## Max. :6.000 Max. :10.000
## NA's :406
Los apartamentos de la Zona Sur tienen un precio promedio de
$297.3 millones (mediana: $245 millones), con un área
construida promedio de 97.5 m² (mediana: 85 m²). Comparado con
las casas de la Zona Norte, los apartamentos presentan áreas
significativamente menores y precios más concentrados, lo cual es
consistente con la tipología de vivienda vertical. La variable
parqueaderos presenta 406 valores faltantes (14.6%).
plot_ly(base2, x = ~preciom, type = "histogram", nbinsx = 40,
marker = list(color = "darkgreen",
line = list(color = "white", width = 0.5))) %>%
layout(title = "Distribución del precio — Apartamentos Zona Sur",
xaxis = list(title = "Precio (millones COP)"),
yaxis = list(title = "Frecuencia"))La distribución del precio es asimétrica positiva, con la mayor concentración entre $100 y $400 millones. Se observa una cola derecha extendida con algunos apartamentos de lujo que superan los $1.000 millones, probablemente ubicados en barrios exclusivos como Ciudad Jardín o sectores de estrato 6.
plot_ly(base2, x = ~areaconst, y = ~preciom, color = ~factor(estrato),
type = "scatter", mode = "markers",
text = ~paste("Barrio:", barrio, "<br>Estrato:", estrato,
"<br>Baños:", banios, "<br>Hab:", habitaciones),
hoverinfo = "text+x+y",
marker = list(size = 5, opacity = 0.6)) %>%
layout(title = "Precio vs. Área construida (por estrato)",
xaxis = list(title = "Área construida (m²)"),
yaxis = list(title = "Precio (millones COP)"),
legend = list(title = list(text = "Estrato")))Se observa una relación positiva fuerte y clara entre el área construida y el precio. La segmentación por estrato es aún más pronunciada que en el caso de las casas: para un área similar, los apartamentos de estrato 6 pueden costar el doble o más que los de estrato 3. Se aprecia también una mayor densidad de puntos en áreas pequeñas (50–120 m²), reflejando la oferta predominante en el mercado de apartamentos.
plot_ly(base2, x = ~factor(estrato), y = ~preciom, type = "box",
color = ~factor(estrato),
colors = c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728")) %>%
layout(title = "Distribución del precio por estrato — Apartamentos Zona Sur",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio (millones COP)"),
showlegend = FALSE)El gradiente de precios por estrato es evidente donde la mediana del estrato 3 ronda los $130 millones, mientras que la del estrato 6 supera los $400 millones. El estrato 6, además, presenta la mayor dispersión con múltiples outliers superiores, reflejando la heterogeneidad del segmento de lujo.
plot_ly(base2, x = ~factor(banios), y = ~preciom, type = "box",
color = ~factor(banios)) %>%
layout(title = "Precio por número de baños",
xaxis = list(title = "Número de baños"),
yaxis = list(title = "Precio (millones COP)"),
showlegend = FALSE)plot_ly(base2, x = ~factor(habitaciones), y = ~preciom, type = "box",
color = ~factor(habitaciones)) %>%
layout(title = "Precio por número de habitaciones",
xaxis = list(title = "Número de habitaciones"),
yaxis = list(title = "Precio (millones COP)"),
showlegend = FALSE)El número de baños muestra una relación monotónicamente creciente con el precio, consistente con la expectativa teórica. El número de habitaciones, sin embargo, presenta un comportamiento interesante: la mediana del precio no siempre aumenta con más habitaciones, lo cual puede explicarse porque en apartamentos, más habitaciones con menor área individual puede significar una distribución menos eficiente del espacio.
vars_num2 <- base2 %>%
select(preciom, areaconst, estrato, banios, habitaciones, parqueaderos)
cor_mat2 <- cor(vars_num2, use = "complete.obs")
plot_ly(
x = colnames(cor_mat2), y = colnames(cor_mat2),
z = cor_mat2, type = "heatmap",
colorscale = "RdBu", zmin = -1, zmax = 1,
text = round(cor_mat2, 2), hoverinfo = "text"
) %>%
layout(title = "Matriz de correlación — Apartamentos Zona Sur",
xaxis = list(tickangle = -45))La correlación más fuerte es nuevamente entre el área construida y el precio (r ≈ 0.74), seguida por baños y parqueaderos. La correlación entre habitaciones y precio es menor, lo cual es consistente con el análisis gráfico previo. Se observan correlaciones moderadas entre baños y área construida (r ≈ 0.66), que ameritan vigilancia de multicolinealidad.
\[\text{preciom} = \beta_0 + \beta_1 \cdot \text{areaconst} + \beta_2 \cdot \text{estrato} + \beta_3 \cdot \text{habitaciones} + \beta_4 \cdot \text{parqueaderos} + \beta_5 \cdot \text{banios} + \varepsilon\]
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
tidy(modelo2, conf.int = TRUE) %>%
mutate(across(where(is.numeric), ~round(., 4))) %>%
kable(caption = "Coeficientes estimados — Modelo 2 (Apartamentos Zona Sur)",
col.names = c("Variable", "Estimación", "Error Estándar",
"Estadístico t", "p-valor", "IC 95% Inf.", "IC 95% Sup.")) %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| Variable | Estimación | Error Estándar | Estadístico t | p-valor | IC 95% Inf. | IC 95% Sup. |
|---|---|---|---|---|---|---|
| (Intercept) | -261.6250 | 15.6322 | -16.7363 | 0 | -292.2792 | -230.9708 |
| areaconst | 1.2850 | 0.0540 | 23.7853 | 0 | 1.1791 | 1.3910 |
| estrato | 60.8971 | 3.0841 | 19.7457 | 0 | 54.8493 | 66.9448 |
| habitaciones | -24.8369 | 3.8923 | -6.3811 | 0 | -32.4696 | -17.2043 |
| parqueaderos | 72.9147 | 3.9580 | 18.4223 | 0 | 65.1533 | 80.6761 |
| banios | 50.6967 | 3.3964 | 14.9267 | 0 | 44.0366 | 57.3569 |
Todos los coeficientes del Modelo 2 resultan altamente
significativos (p < 0.001), lo cual contrasta con el Modelo
1 donde habitaciones no fue significativa. A continuación
se interpretan los resultados:
Intercepto (β₀ = –261.63, p < 0.001): el valor teórico sin interpretación práctica directa.
Área construida (β₁ = 1.285, p < 0.001): por cada metro cuadrado adicional, el precio del apartamento aumenta en $1.29 millones (≈ $1.285.000 COP). Este efecto es casi el doble del observado en casas ($0.68M), lo cual tiene sentido: en el mercado de apartamentos en estratos altos, el metro cuadrado se cotiza a valores superiores debido a que las unidades disponibles tienden a ser de menor tamaño y el precio por unidad de área es más elevado.
Estrato (β₂ = 60.90, p < 0.001): cada nivel adicional de estrato incrementa el precio en $60.9 millones. Aunque el efecto es significativo y sustantivo, resulta menor que en las casas ($80.6M), posiblemente porque en apartamentos la diferenciación por estrato se diluye en parte por la estandarización de las construcciones verticales.
Habitaciones (β₃ = –24.84, p < 0.001): este es el resultado más llamativo del modelo: cada habitación adicional se asocia con una disminución de $24.8 millones en el precio. Si bien esto puede parecer contraintuitivo a primera vista, tiene una explicación razonable en el contexto del mercado de apartamentos: controlando por el área construida y el estrato, un mayor número de habitaciones en el mismo espacio implica habitaciones más pequeñas y una distribución menos eficiente del espacio. Los apartamentos con diseños más abiertos y espaciosos (tipo open concept) o con menos habitaciones pero de mayor tamaño suelen percibirse como de mayor calidad y, por ende, se valorizan más. Este fenómeno es conocido en la literatura inmobiliaria como el efecto del “tamaño promedio de habitación”.
Parqueaderos (β₄ = 72.91, p < 0.001): cada parqueadero adicional incrementa el precio en $72.9 millones. Este es el segundo efecto más fuerte del modelo y es tres veces mayor que en casas ($24M). En el contexto de apartamentos —particularmente en estratos altos del sur de Cali—, los parqueaderos son un activo escaso y altamente valorado, ya que las unidades de vivienda vertical frecuentemente tienen restricciones de espacio para estacionamiento.
Baños (β₅ = 50.70, p < 0.001): cada baño adicional se asocia con un incremento de $50.7 millones, efecto considerablemente mayor al observado en casas ($18.9M). En apartamentos, los baños adicionales suelen ser un indicador de acabados de alta gama y de un mayor nivel de lujo.
r2_2 <- summary(modelo2)$r.squared
r2_adj_2 <- summary(modelo2)$adj.r.squared
data.frame(
Métrica = c("R²", "R² ajustado", "Error estándar residual", "Observaciones utilizadas"),
Valor = c(round(r2_2, 4), round(r2_adj_2, 4), "98.02 millones", "2,381 (de 2,787)")
) %>%
kable(caption = "Indicadores de ajuste — Modelo 2") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Métrica | Valor |
|---|---|
| R² | 0.7485 |
| R² ajustado | 0.748 |
| Error estándar residual | 98.02 millones |
| Observaciones utilizadas | 2,381 (de 2,787) |
El Modelo 2 explica el 74.9% de la variabilidad del precio (R² = 0.7485; R² ajustado = 0.748), lo que representa un ajuste sustancialmente mejor que el Modelo 1 (60.4%). Esto puede atribuirse a un mayor tamaño muestral (2,381 vs. 435 observaciones efectivas); una mayor homogeneidad en el mercado de apartamentos respecto al de casas; y la significancia de todos los predictores del modelo.
##
## Shapiro-Wilk normality test
##
## data: residuals(modelo2)
## W = 0.79118, p-value < 2.2e-16
qq_data2 <- data.frame(
teorico = qqnorm(residuals(modelo2), plot.it = FALSE)$x,
muestral = qqnorm(residuals(modelo2), plot.it = FALSE)$y
)
plot_ly(qq_data2, x = ~teorico, y = ~muestral,
type = "scatter", mode = "markers",
marker = list(color = "darkgreen", size = 3, opacity = 0.5)) %>%
add_trace(x = c(-4, 4), y = c(-4 * sd(residuals(modelo2)), 4 * sd(residuals(modelo2))),
type = "scatter", mode = "lines",
line = list(color = "red", dash = "dash"), name = "Referencia") %>%
layout(title = "Q-Q Plot de residuos — Modelo 2",
xaxis = list(title = "Cuantiles teóricos"),
yaxis = list(title = "Cuantiles muestrales"),
showlegend = FALSE)El test de Shapiro-Wilk (W = 0.7912, p < 2.2 × 10⁻¹⁶) rechaza la normalidad de los residuos de forma aún más pronunciada que en el Modelo 1. El Q-Q plot evidencia desviaciones severas en ambas colas, con una cola derecha particularmente pesada. La mayor severidad de esta violación se explica por la presencia de apartamentos de lujo con precios muy por encima de la tendencia general.
##
## studentized Breusch-Pagan test
##
## data: modelo2
## BP = 754.81, df = 5, p-value < 2.2e-16
El test de Breusch-Pagan (BP = 754.81, df = 5, p < 2.2 × 10⁻¹⁶) indica una heterocedasticidad muy severa, corroborada por el patrón de embudo ampliamente visible en los diagnósticos gráficos. La variabilidad del error de predicción aumenta dramáticamente para apartamentos de mayor precio.
##
## Durbin-Watson test
##
## data: modelo2
## DW = 1.5333, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
El test de Durbin-Watson (DW = 1.533, p < 2.2 × 10⁻¹⁶) indica autocorrelación positiva significativa. Dado que no existe un ordenamiento temporal natural en estos datos de corte transversal, esta autocorrelación probablemente refleja dependencia espacial: los apartamentos cercanos geográficamente comparten factores de valorización no capturados por el modelo (calidad del barrio, cercanía a parques, infraestructura vial, etc.).
vif_df2 <- vif(modelo2) %>%
as.data.frame() %>%
rownames_to_column("Variable")
names(vif_df2)[2] <- "VIF"
vif_df2 %>%
mutate(VIF = round(VIF, 3),
Diagnóstico = ifelse(VIF < 5, "Aceptable", "Problemático")) %>%
kable(caption = "Factores de Inflación de Varianza (VIF) — Modelo 2") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Variable | VIF | Diagnóstico |
|---|---|---|
| areaconst | 2.067 | Aceptable |
| estrato | 1.545 | Aceptable |
| habitaciones | 1.429 | Aceptable |
| parqueaderos | 1.738 | Aceptable |
| banios | 2.529 | Aceptable |
Todos los valores de VIF se encuentran por debajo de
2.6, confirmando la ausencia de multicolinealidad
problemática. El valor más elevado corresponde a
banios (VIF ≈ 2.53), seguido de areaconst (VIF
≈ 2.07), lo cual es esperado por la correlación natural entre área y
número de baños.
Supuesto Test / Método
Resultado Conclusión Normalidad
Shapiro-Wilk W = 0.791, p < 0.001 Violado (severo)
Homocedasticidad Breusch-Pagan BP = 754.8, p < 0.001 Violado
(severo) Independencia Durbin-Watson DW = 1.533, p < 0.001
Violado
No multicolinealidad VIF Todos < 2.6 Cumple
A continuación, se predice el precio para un apartamento de 300 m², 5 habitaciones, 3 parqueaderos y 3 baños, en los escenarios de estrato 5 y 6:
vivienda2_e5 <- data.frame(areaconst = 300, estrato = 5,
habitaciones = 5, parqueaderos = 3, banios = 3)
vivienda2_e6 <- data.frame(areaconst = 300, estrato = 6,
habitaciones = 5, parqueaderos = 3, banios = 3)
pred2_e5 <- predict(modelo2, newdata = vivienda2_e5, interval = "prediction", level = 0.95)
pred2_e6 <- predict(modelo2, newdata = vivienda2_e6, interval = "prediction", level = 0.95)
rbind(
data.frame(Escenario = "Estrato 5", round(as.data.frame(pred2_e5), 2)),
data.frame(Escenario = "Estrato 6", round(as.data.frame(pred2_e6), 2))
) %>%
rename("Predicción (M COP)" = fit,
"Lím. Inferior 95%" = lwr,
"Lím. Superior 95%" = upr) %>%
kable(caption = "Predicción del precio — Vivienda 2") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| Escenario | Predicción (M COP) | Lím. Inferior 95% | Lím. Superior 95% | |
|---|---|---|---|---|
| 1 | Estrato 5 | 675.02 | 481.45 | 868.59 |
| 11 | Estrato 6 | 735.92 | 542.31 | 929.53 |
Análisis de las predicciones:
Estrato 5: el precio estimado es de $675.0 millones (IC 95%: $481.5 – $868.6 millones). La predicción puntual se sitúa holgadamente dentro del presupuesto de $850 millones.
Estrato 6: el precio estimado es de $735.9 millones (IC 95%: $542.3 – $929.5 millones). La predicción puntual también queda dentro del presupuesto, aunque el límite superior del intervalo ($929.5M) lo supera. Esto indica que en estrato 6 existe riesgo de que algunas propiedades excedan los $850 millones.
En ambos escenarios, los intervalos de predicción son amplios (≈ $387 millones), lo cual refleja la variabilidad inherente al mercado de apartamentos de alta gama. No obstante, el ajuste superior del Modelo 2 (R² = 0.75) ofrece mayor confianza en las predicciones puntuales que el Modelo 1.
Se filtran apartamentos en la Zona Sur, estrato 5 o 6, con ≥ 4 habitaciones, ≥ 3 baños, ≥ 2 parqueaderos y precio ≤ $850 millones:
ofertas2 <- base2 %>%
filter(
preciom <= 850,
estrato %in% c(5, 6),
habitaciones >= 4,
banios >= 3,
parqueaderos >= 2
) %>%
arrange(desc(areaconst))
cat("Total de ofertas que cumplen las condiciones:", nrow(ofertas2))## Total de ofertas que cumplen las condiciones: 190
top5_ofertas2 <- ofertas2 %>% head(5)
top5_ofertas2 %>%
select(barrio, preciom, areaconst, estrato, habitaciones, banios, parqueaderos) %>%
mutate(
`Precio/m²` = round(preciom / areaconst, 2)
) %>%
kable(caption = "Top 5 ofertas recomendadas — Vivienda 2 (≤ $850M)",
col.names = c("Barrio", "Precio (M)", "Área (m²)", "Estrato",
"Hab.", "Baños", "Parq.", "Precio/m² (M)")) %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| Barrio | Precio (M) | Área (m²) | Estrato | Hab. | Baños | Parq. | Precio/m² (M) |
|---|---|---|---|---|---|---|---|
| el ingenio | 650 | 600 | 5 | 5 | 4 | 2 | 1.08 |
| guadalupe | 730 | 573 | 5 | 5 | 8 | 3 | 1.27 |
| el ingenio | 690 | 486 | 5 | 4 | 4 | 2 | 1.42 |
| san fernando | 500 | 330 | 5 | 4 | 4 | 2 | 1.52 |
| cuarto de legua | 520 | 320 | 5 | 4 | 4 | 2 | 1.62 |
leaflet(top5_ofertas2) %>%
addTiles() %>%
addCircleMarkers(
~longitud, ~latitud,
radius = 9, color = "purple", fillOpacity = 0.85,
popup = ~paste0(
"<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio:</b> $", preciom, " M<br>",
"<b>Área:</b> ", areaconst, " m²<br>",
"<b>Estrato:</b> ", estrato, "<br>",
"<b>Hab:</b> ", habitaciones, " | <b>Baños:</b> ", banios,
" | <b>Parq:</b> ", parqueaderos
),
label = ~paste0("$", preciom, "M — ", barrio)
) %>%
addLegend("bottomright", colors = "purple", labels = "Ofertas recomendadas")Discusión de las ofertas:
El Ingenio ($650M, 600 m², estrato 5): la oferta con la mejor relación precio/m² ($1.08M/m²) y un área que duplica el requerimiento mínimo. Con 5 habitaciones y 4 baños, cumple holgadamente con las especificaciones. Representa un excelente valor.
Guadalupe ($730M, 573 m², estrato 5): un apartamento de gran tamaño con 8 baños, lo que sugiere un acabado de alta gama o una configuración tipo penthouse. El precio por metro cuadrado es competitivo ($1.27M/m²).
El Ingenio ($690M, 486 m², estrato 5): segunda opción en el mismo barrio. Ofrece 4 habitaciones y 4 baños. El precio por m² ($1.42M) es razonable.
San Fernando ($500M, 330 m², estrato 5) y Cuarto de Legua ($520M, 320 m², estrato 5): son las opciones más económicas que dejan margen presupuestal significativo, con áreas que cumplen con el requerimiento de 300 m².
Recomendación: se destaca la oferta de El Ingenio ($650M, 600 m²) como la opción óptima, dado que ofrece el mejor equilibrio entre precio, área y ubicación. El barrio El Ingenio es reconocido por su infraestructura consolidada, acceso a centros comerciales y vías principales, lo cual resulta especialmente atractivo para familias en proceso de reubicación. Las opciones de San Fernando y Cuarto de Legua representan alternativas más conservadoras que maximizan el ahorro.
data.frame(
Indicador = c("Tipo de vivienda", "Zona", "Observaciones totales", "Observaciones en modelo",
"R²", "R² ajustado", "Error estándar residual",
"Variables significativas (α = 0.05)", "Predicción puntual (escenario principal)",
"Crédito preaprobado", "¿Dentro de presupuesto?"),
Modelo_1 = c("Casa", "Norte", "722", "435", "0.6041", "0.5995", "$155.1M",
"4 de 5", "$312.1M (est. 4) / $392.7M (est. 5)",
"$350M", "Sí (est. 4) / Ajustado (est. 5)"),
Modelo_2 = c("Apartamento", "Sur", "2,787", "2,381", "0.7485", "0.7480", "$98.0M",
"5 de 5", "$675.0M (est. 5) / $735.9M (est. 6)",
"$850M", "Sí (ambos estratos)")
) %>%
kable(caption = "Comparación integral de los dos modelos",
col.names = c("Indicador", "Modelo 1 (Casas Norte)", "Modelo 2 (Aptos. Sur)")) %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| Indicador | Modelo 1 (Casas Norte) | Modelo 2 (Aptos. Sur) |
|---|---|---|
| Tipo de vivienda | Casa | Apartamento |
| Zona | Norte | Sur |
| Observaciones totales | 722 | 2,787 |
| Observaciones en modelo | 435 | 2,381 |
| R² | 0.6041 | 0.7485 |
| R² ajustado | 0.5995 | 0.7480 |
| Error estándar residual | $155.1M | $98.0M |
| Variables significativas (α = 0.05) | 4 de 5 | 5 de 5 |
| Predicción puntual (escenario principal) | $312.1M (est. 4) / $392.7M (est. 5) | $675.0M (est. 5) / $735.9M (est. 6) |
| Crédito preaprobado | $350M | $850M |
| ¿Dentro de presupuesto? | Sí (est. 4) / Ajustado (est. 5) | Sí (ambos estratos) |
Sobre la modelación: se estimaron dos modelos de regresión lineal múltiple con niveles de ajuste moderado (R² = 0.60) y bueno (R² = 0.75), respectivamente. En ambos casos, el área construida y el estrato socioeconómico resultaron ser los predictores con mayor impacto sobre el precio. El modelo de apartamentos (Zona Sur) presentó un mejor ajuste, lo cual se atribuye a una muestra más grande y un mercado más homogéneo.
Sobre los supuestos: ambos modelos presentaron violaciones de normalidad y homocedasticidad, lo cual es frecuente en datos inmobiliarios debido a la presencia de propiedades de lujo que generan colas pesadas en la distribución de precios. Ningún modelo presentó problemas de multicolinealidad. Para futuras iteraciones, se recomienda la transformación logarítmica del precio.
Sobre la Vivienda 1 (Casa, Zona Norte): la predicción del modelo sugiere que una casa de 200 m² en estrato 4 costaría aproximadamente $312 millones, cifra que se ajusta al presupuesto de $350 millones. Se identificaron ofertas concretas en barrios como San Vicente, Salomia y El Bosque que representan opciones viables y con áreas superiores a lo requerido.
Sobre la Vivienda 2 (Apartamento, Zona Sur): el modelo predice un precio de $675 millones (estrato 5) a $736 millones (estrato 6), ambos dentro del crédito preaprobado de $850 millones. Las ofertas disponibles en El Ingenio y Guadalupe destacan por su excelente relación precio-área.
Recomendación general a María: se sugiere presentar a la empresa solicitante un portafolio acotado con las mejores opciones identificadas, priorizando la relación precio/m² y la ubicación estratégica para familias en proceso de reubicación. Se recomienda complementar este análisis cuantitativo con visitas presenciales para evaluar el estado de conservación, la seguridad del sector y la accesibilidad a servicios educativos y de salud.