María, fundadora de la agencia C&A (Casas y Apartamentos) en Cali, recibió una solicitud de una compañía internacional para ubicar a dos empleados con sus familias en la ciudad. Las características requeridas se resumen a continuación:
| Característica | Vivienda 1 — Casa | Vivienda 2 — Apartamento |
|---|---|---|
| Tipo | Casa | Apartamento |
| Área construida | 200 m² | 300 m² |
| Parqueaderos | 1 | 3 |
| Baños | 2 | 3 |
| Habitaciones | 4 | 5 |
| Estrato | 4 ó 5 | 5 ó 6 |
| Zona | Norte | Sur |
| Crédito preaprobado | $350 millones | $850 millones |
Realice un filtro a la base de datos e incluya solo las ofertas de casas de la zona norte de la ciudad. Presente los primeros 3 registros y algunas tablas que comprueben la consulta. Adicione un mapa con los puntos de las bases y discuta si todos se ubican en la zona correspondiente.
base1 <- vivienda %>%
filter(tipo == "Casa", zona == "Zona Norte")
cat("Total de registros en base1:", nrow(base1), "\n")## Total de registros en base1: 722
Tabla 1. Primeros 3 registros — Casas Zona Norte
base1 %>%
head(3) %>%
kable(digits = 1, align = "c") %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = TRUE)| 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.5 | 3.5 |
| 1592 | Zona Norte | 02 | 5 | 780 | 380 | 2 | 3 | 3 | Casa | acopi | -76.5 | 3.5 |
| 4057 | Zona Norte | 02 | 6 | 750 | 445 | NA | 7 | 6 | Casa | acopi | -76.5 | 3.4 |
Verificación del filtro:
Tabla 2. Verificación de tipo de vivienda
kable(as.data.frame(table(Tipo = base1$tipo)), align = "c") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Tipo | Freq |
|---|---|
| Casa | 722 |
Tabla 3. Verificación de zona
kable(as.data.frame(table(Zona = base1$zona)), align = "c") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Zona | Freq |
|---|---|
| Zona Norte | 722 |
Tabla 4. Distribución por estrato — Casas Zona Norte
kable(as.data.frame(table(Estrato = base1$estrato)), align = "c") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)| Estrato | Freq |
|---|---|
| 3 | 235 |
| 4 | 161 |
| 5 | 271 |
| 6 | 55 |
Tabla 5. Estadísticas descriptivas del precio — Casas Zona Norte (millones COP)
base1 %>%
summarise(
Minimo = min(preciom, na.rm=TRUE),
Q1 = quantile(preciom, 0.25, na.rm=TRUE),
Mediana = median(preciom, na.rm=TRUE),
Media = mean(preciom, na.rm=TRUE),
Q3 = quantile(preciom, 0.75, na.rm=TRUE),
Maximo = max(preciom, na.rm=TRUE),
Des.Est = sd(preciom, na.rm=TRUE)
) %>%
kable(digits = 1, align = "c") %>%
kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE)| Minimo | Q1 | Mediana | Media | Q3 | Maximo | Des.Est |
|---|---|---|---|---|---|---|
| 89 | 261.2 | 390 | 445.9 | 550 | 1940 | 268.4 |
Figura 1. Mapa interactivo de ubicaciones — Casas Zona Norte
pal1 <- colorFactor(
palette = c("4"="#1565C0","5"="#FF9800","6"="#43A047"),
domain = as.character(base1$estrato)
)
leaflet(base1) %>%
addProviderTiles(providers$OpenStreetMap) %>%
setView(lng = -76.535, lat = 3.470, zoom = 13) %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
radius = 7, color = ~pal1(as.character(estrato)),
stroke = TRUE, weight = 1, fillOpacity = 0.85,
popup = ~paste0(
"<b>Barrio:</b> ", barrio, "<br>",
"<b>Estrato:</b> ", estrato, "<br>",
"<b>Area:</b> ", areaconst, " m2<br>",
"<b>Precio:</b> $", preciom, "M"
)
) %>%
addLegend(position = "bottomright", pal = pal1,
values = ~as.character(estrato),
title = "Estrato", opacity = 0.9)Interpretacion — Mapa base1: Los 722 registros de casas en la Zona Norte se distribuyen en la franja norte de Cali, con la mayor concentracion de puntos en la latitud correspondiente a esta zona. La distribucion por estrato muestra predominancia de estrato 5 (271 casas), seguido de estrato 3 (235), estrato 4 (161) y estrato 6 (55), reflejando la diversidad socioeconomica de la Zona Norte. El precio oscila entre $89M y $1,940M con una media de $445.9M. Pueden aparecer algunos puntos en zonas limitrofes por imprecision en los limites administrativos de la base de datos o por barrios cuya extension territorial cruza denominaciones zonales. Este comportamiento es esperado y no invalida el filtro aplicado.
Realice un analisis exploratorio de datos enfocado en la correlacion entre el precio de la casa en funcion del area construida, estrato, numero de banos, numero de habitaciones y parqueaderos. Use graficos interactivos con el paquete
plotlye interprete los resultados.
Tabla 6. Matriz de correlaciones de Pearson — Casas Zona Norte
vars_num <- base1 %>%
dplyr::select(preciom, areaconst, estrato, banios, habitaciones, parqueaderos)
cor_matrix <- round(cor(vars_num, use = "complete.obs"), 3)
kable(cor_matrix, align = "c") %>%
kable_styling(bootstrap_options = c("striped","hover","condensed"))| preciom | areaconst | estrato | banios | habitaciones | parqueaderos | |
|---|---|---|---|---|---|---|
| preciom | 1.000 | 0.685 | 0.528 | 0.509 | 0.365 | 0.412 |
| areaconst | 0.685 | 1.000 | 0.354 | 0.457 | 0.421 | 0.307 |
| estrato | 0.528 | 0.354 | 1.000 | 0.351 | 0.058 | 0.261 |
| banios | 0.509 | 0.457 | 0.351 | 1.000 | 0.590 | 0.392 |
| habitaciones | 0.365 | 0.421 | 0.058 | 0.590 | 1.000 | 0.241 |
| parqueaderos | 0.412 | 0.307 | 0.261 | 0.392 | 0.241 | 1.000 |
Figura 2. Precio vs. Area Construida por estrato — Casas Zona Norte
plot_ly(
data = base1,
x = ~areaconst,
y = ~preciom,
color = ~factor(estrato),
colors = c("4"="#1565C0","5"="#FF9800","6"="#43A047"),
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.75),
text = ~paste0("Barrio: ", barrio,
"<br>Area: ", areaconst, " m2",
"<br>Precio: $", preciom, "M",
"<br>Estrato: ", estrato),
hoverinfo = "text"
) %>%
layout(
title = list(text = "<b>Precio vs. Area Construida — Casas Zona Norte</b>"),
xaxis = list(title = "Area Construida (m2)"),
yaxis = list(title = "Precio (millones $)"),
legend = list(title = list(text = "<b>Estrato</b>"))
)Interpretacion: Se observa una correlacion positiva moderada-fuerte entre el area construida y el precio (r = 0.685). A mayor area, el precio tiende a subir aunque con mayor dispersion que en modelos mas homogeneos. Los colores por estrato muestran un desplazamiento vertical notable: para el mismo tamano de propiedad, el precio es considerablemente mayor en estrato 6 que en estrato 3, evidenciando el efecto del entorno socioeconomico. La presencia de los cuatro estratos (3 al 6) en esta zona genera mayor variabilidad en los precios que lo esperado en una zona de un solo perfil socioeconomico.
Figura 3. Distribucion del precio por estrato — Casas Zona Norte
plot_ly(
data = base1,
x = ~factor(estrato),
y = ~preciom,
color = ~factor(estrato),
colors = c("4"="#1565C0","5"="#FF9800","6"="#43A047"),
type = "box", boxpoints = "outliers",
text = ~paste0("Barrio: ", barrio, "<br>Precio: $", preciom, "M"),
hoverinfo = "text+y"
) %>%
layout(
title = list(text = "<b>Precio por Estrato — Casas Zona Norte</b>"),
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio (millones $)"),
showlegend = FALSE
)Interpretacion: La mediana del precio aumenta con el estrato socioeconomico (r = 0.528). El estrato 6 presenta la mediana mas alta y mayor dispersion, con bigotes superiores muy amplios que reflejan propiedades premium de alto valor. El estrato 3, aunque tiene el precio mediano mas bajo, tambien muestra valores atipicos superiores, lo que indica que en la Zona Norte conviven propiedades de perfil muy diverso. La correlacion de Pearson entre estrato y precio es moderada-fuerte (r = 0.528), la segunda mas alta despues del area.
Figura 4. Precio vs. Numero de habitaciones por estrato — Casas Zona Norte
plot_ly(
data = base1,
x = ~factor(habitaciones),
y = ~preciom,
color = ~factor(estrato),
colors = c("4"="#1565C0","5"="#FF9800","6"="#43A047"),
type = "box", hoverinfo = "y"
) %>%
layout(
title = list(text = "<b>Precio vs. Habitaciones — Casas Zona Norte</b>"),
xaxis = list(title = "Numero de habitaciones"),
yaxis = list(title = "Precio (millones $)"),
legend = list(title = list(text = "<b>Estrato</b>"))
)Interpretacion: A mayor numero de habitaciones el precio tiende a aumentar, con una correlacion moderada (r = 0.365), la mas baja entre los predictores pero no despreciable. Esta relacion refleja que casas con mas habitaciones son mas grandes y en estratos mas altos, capturando indirectamente el efecto conjunto del area y el estrato. La variable no resulta significativa en el modelo de regresion (p = 0.177), lo que indica que su efecto queda absorbido por las demas variables una vez se controla por area y estrato.
Figura 5. Heatmap de correlaciones — Casas Zona Norte
cor_df <- as.data.frame(as.table(cor_matrix))
names(cor_df) <- c("Var1","Var2","Correlacion")
plot_ly(
data = cor_df, x = ~Var1, y = ~Var2, z = ~Correlacion,
type = "heatmap",
colorscale = list(c(0,"#d32f2f"), c(0.5,"white"), c(1,"#1b5e20")),
zmin = -1, zmax = 1,
hovertemplate = "<b>%{x}</b> vs <b>%{y}</b><br>r = %{z:.3f}<extra></extra>"
) %>%
layout(
title = list(text = "<b>Heatmap de Correlaciones — Casas Zona Norte</b>"),
xaxis = list(title = ""),
yaxis = list(title = "")
)Interpretacion general: En casas de la Zona Norte,
areaconst presenta la correlacion mas fuerte con el precio
(r = 0.685), seguida de estrato (r = 0.528),
banios (r = 0.509), parqueaderos (r = 0.412) y
habitaciones (r = 0.365). A diferencia de lo esperado,
todas las variables muestran correlaciones moderadas con el precio, no
solo el area. Destaca la correlacion alta entre banios y
habitaciones (r = 0.590) y entre areaconst y
banios (r = 0.457), lo que anticipa posible
multicolinealidad entre predictores y sugiere que algunas variables
podrian no ser independientemente significativas en el modelo de
regresion.
Estime un modelo de regresion lineal multiple con las variables: precio = f(area construida, estrato, habitaciones, parqueaderos, banos). Interprete los coeficientes estadisticamente significativos, el R2 y discuta el ajuste del modelo.
El modelo estimado tiene la siguiente forma funcional:
\[\widehat{\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}\]
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
Tabla 7. Coeficientes del modelo — Casas Zona Norte (variables significativas resaltadas)
coefs1 <- as.data.frame(summary(modelo1)$coefficients)
coefs1$Sig <- ifelse(coefs1[,4]<0.001,"***",
ifelse(coefs1[,4]<0.01, "**",
ifelse(coefs1[,4]<0.05, "*",
ifelse(coefs1[,4]<0.1, ".", "NS"))))
names(coefs1)[1:4] <- c("Estimado","Error Std.","Estadistico t","p-valor")
kable(coefs1, digits=4, align="c") %>%
kable_styling(bootstrap_options=c("striped","hover","condensed")) %>%
row_spec(which(coefs1$`p-valor` < 0.05),
bold=TRUE, color="white", background="#1565C0")| Estimado | Error Std. | Estadistico t | p-valor | Sig | |
|---|---|---|---|---|---|
| (Intercept) | -238.1709 | 44.4055 | -5.3635 | 0.0000 | *** |
| areaconst | 0.6767 | 0.0528 | 12.8140 | 0.0000 | *** |
| estrato | 80.6349 | 9.8263 | 8.2060 | 0.0000 | *** |
| habitaciones | 7.6451 | 5.6587 | 1.3510 | 0.1774 | NS |
| parqueaderos | 24.0060 | 5.8689 | 4.0904 | 0.0001 | *** |
| banios | 18.8994 | 7.4880 | 2.5240 | 0.0120 |
|
Tabla 8. Factores de Inflacion de Varianza (VIF) — Modelo 1
kable(as.data.frame(vif(modelo1)), col.names="VIF", digits=3, align="c") %>%
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE)| VIF | |
|---|---|
| areaconst | 1.461 |
| estrato | 1.308 |
| habitaciones | 1.721 |
| parqueaderos | 1.226 |
| banios | 1.967 |
Interpretacion de coeficientes significativos (p < 0.05):
areaconst (β = 0.6767, ***): Por
cada metro cuadrado adicional de area construida, el precio de la casa
aumenta en promedio $0.68 millones, manteniendo las
demas variables constantes (t = 12.814, p < 2e-16). Es el predictor
con mayor significancia estadistica del modelo, coherente con el mercado
inmobiliario donde el area es la dimension fisica fundamental del
valor.
estrato (β = 80.6350, ***): Subir
un nivel de estrato socioeconomico se asocia con un incremento promedio
de $80.63 millones en el precio (t = 8.206, p =
2.70e-15). Es el coeficiente de mayor magnitud del modelo, capturando
calidad urbanistica, acceso a servicios, seguridad y valorizacion del
vecindario en la Zona Norte de Cali.
parqueaderos (β = 24.0060, ***):
Cada parqueadero adicional agrega en promedio $24.01
millones al precio (t = 4.090, p = 5.14e-05). En casas de la
Zona Norte, el parqueadero es un diferenciador de valor relevante,
posiblemente por la escasez de espacio de parqueo en zonas
densas.
banios (β = 18.8994, *): Cada bano
adicional agrega $18.90 millones (t = 2.524, p =
0.012). Aunque significativo al 5%, presenta el menor nivel de
significancia entre las variables significativas, indicando un efecto
marginal real pero moderado una vez controladas las demas
variables.
habitaciones (β = 7.6451, NS): No
es estadisticamente significativa (p = 0.177). Su efecto queda absorbido
por el area construida y los banos, con los cuales esta correlacionada
(r = 0.590 con banios, r = 0.421 con areaconst).
R² = 0.6041 (R² ajustado = 0.5995): El modelo explica el 60.4% de la variabilidad en el precio de las casas de la Zona Norte, con un error estandar residual de $155.1 millones. El ajuste es moderado; el 39.6% restante refleja la alta heterogeneidad de precios en esta zona (rango $89M–$1,940M) y variables no incluidas como antiguedad, calidad de acabados, estado de conservacion y efectos de barrio. Cabe notar que 287 observaciones fueron eliminadas por valores faltantes (NA), lo que puede introducir sesgo si la ausencia de datos no es aleatoria.
Como mejorar el modelo: Incluir barrio
como factor de efectos fijos, agregar antiguedad de la
construccion, aplicar transformacion logaritmica al precio para
estabilizar la varianza (recomendado dado el amplio rango de precios), o
explorar modelos de regresion geoespacial (GWR).
Multicolinealidad: Los VIF oscilan entre 1.226 (parqueaderos) y 1.967 (banios), todos por debajo del umbral de 5. No existe multicolinealidad problematica, aunque los valores de banios y habitaciones (VIF=1.721 y 1.967) son los mas elevados, consistente con su alta correlacion bivariada (r = 0.590).
Realice la validacion de supuestos del modelo e interprete los resultados. No es necesario corregir en caso de presentar problemas, solo realizar sugerencias.
Figura 6. Graficos de diagnostico del modelo — Casas Zona Norte
Figura 7. Histograma de residuos con curva normal teorica — Modelo 1
res1 <- residuals(modelo1)
data.frame(residuos = res1) %>%
ggplot(aes(x = residuos)) +
geom_histogram(aes(y = after_stat(density)), bins=15,
fill="#1565C0", color="white", alpha=0.8) +
stat_function(fun=dnorm, args=list(mean=0, sd=sd(res1)),
color="#c62828", linewidth=1.2) +
labs(x="Residuos", y="Densidad") +
theme_minimal(base_size=13)Tabla 9. Pruebas formales de supuestos — Modelo 1
sw1 <- shapiro.test(res1)
bp1 <- bptest(modelo1)
dw1 <- dwtest(modelo1)
data.frame(
Supuesto = c("Normalidad de residuos (Shapiro-Wilk)",
"Homocedasticidad (Breusch-Pagan)",
"Autocorrelacion (Durbin-Watson)"),
Estadistico = round(c(sw1$statistic, bp1$statistic, dw1$statistic), 4),
p.valor = round(c(sw1$p.value, bp1$p.value, dw1$p.value), 4),
Conclusion = c(
ifelse(sw1$p.value>0.05,"Cumple (p > 0.05)","No cumple (p <= 0.05)"),
ifelse(bp1$p.value>0.05,"Cumple (p > 0.05)","No cumple (p <= 0.05)"),
ifelse(dw1$p.value>0.05,"Cumple (p > 0.05)","Indicio (p <= 0.05)")
)
) %>%
kable(align="c") %>%
kable_styling(bootstrap_options=c("striped","hover"))| Supuesto | Estadistico | p.valor | Conclusion | |
|---|---|---|---|---|
| W | Normalidad de residuos (Shapiro-Wilk) | 0.8525 | 0.0000 | No cumple (p <= 0.05) |
| BP | Homocedasticidad (Breusch-Pagan) | 80.2808 | 0.0000 | No cumple (p <= 0.05) |
| DW | Autocorrelacion (Durbin-Watson) | 1.7615 | 0.0055 | Indicio (p <= 0.05) |
Figura 8. Valores reales vs. predichos — Modelo 1
df_pred_m1 <- data.frame(
real = modelo1$model$preciom,
pred = fitted(modelo1)
)
ggplot(df_pred_m1, aes(x=pred, y=real)) +
geom_point(color="#1565C0", alpha=0.7, size=2.5) +
geom_abline(intercept=0, slope=1, color="#c62828",
linetype="dashed", linewidth=1) +
labs(x="Precio Predicho (M$)", y="Precio Real (M$)") +
theme_minimal(base_size=13)Interpretacion de supuestos — Modelo 1:
Normalidad (Shapiro-Wilk W = 0.8525, p < 0.001): Se rechaza H0 (p ≤ 0.05). Los residuos NO siguen distribucion normal. El histograma muestra una distribucion con cola derecha pronunciada (asimetria positiva), consistente con la presencia de propiedades de precio muy alto que el modelo subestima sistematicamente. Este incumplimiento es esperable dado el amplio rango de precios ($89M–$1,940M) y la presencia de valores atipicos en la base.
Homocedasticidad (Breusch-Pagan BP = 80.28, p < 0.001): Se rechaza H0 (p ≤ 0.05). Existe heterocedasticidad significativa. La varianza de los errores no es constante: aumenta con los valores ajustados, lo que se observa en el grafico Scale-Location con una tendencia ascendente. Las propiedades de alto precio tienen errores mucho mayores que las de precio bajo.
Autocorrelacion (Durbin-Watson = 1.7615, p = 0.0055): Se detecta un indicio de autocorrelacion positiva (p ≤ 0.05). Aunque el estadistico DW = 1.76 esta en el rango aceptable, el p-valor sugiere dependencia entre residuos consecutivos, posiblemente por efecto de barrio o proximidad geografica entre propiedades.
Valores reales vs. predichos: El grafico mostrara mayor dispersion en los precios altos, confirmando la heterocedasticidad. El modelo tiende a sobreestimar propiedades baratas y subestimar las caras.
Sugerencias de correccion: (1) Aplicar
transformacion logaritmica al precio:
lm(log(preciom) ~ ...) para estabilizar la varianza y
mejorar la normalidad. (2) Usar errores estandar robustos tipo HC3 con
el paquete sandwich. (3) Incluir efectos fijos de barrio
para capturar dependencia espacial y reducir la autocorrelacion. (4)
Explorar modelos de regresion por cuantiles para no depender del
supuesto de normalidad.
Con el modelo identificado, prediga el precio de la vivienda con las caracteristicas de la primera solicitud.
Las caracteristicas de la Vivienda 1 son: area = 200 m2, estrato 4 o 5, 4 habitaciones, 1 parqueadero, 2 banos, Zona Norte, tipo Casa.
Tabla 10. Prediccion del precio — Vivienda 1 (millones COP)
v1_e4 <- data.frame(areaconst=200, estrato=4, habitaciones=4,
parqueaderos=1, banios=2)
v1_e5 <- data.frame(areaconst=200, estrato=5, habitaciones=4,
parqueaderos=1, banios=2)
pred_e4 <- predict(modelo1, newdata=v1_e4, interval="prediction", level=0.95)
pred_e5 <- predict(modelo1, newdata=v1_e5, interval="prediction", level=0.95)
data.frame(
Escenario = c("Estrato 4","Estrato 5"),
Prediccion = round(c(pred_e4[1], pred_e5[1]), 1),
Lim.Inf.95 = round(c(pred_e4[2], pred_e5[2]), 1),
Lim.Sup.95 = round(c(pred_e4[3], pred_e5[3]), 1),
Presupuesto = 350,
Diferencia = round(c(pred_e4[1]-350, pred_e5[1]-350), 1)
) %>%
kable(align="c",
col.names=c("Escenario","Prediccion ($M)","Lim. Inf. 95%",
"Lim. Sup. 95%","Presupuesto ($M)","Diferencia ($M)")) %>%
kable_styling(bootstrap_options=c("striped","hover")) %>%
row_spec(1:2, bold=TRUE, color="white", background="#c62828")| Escenario | Prediccion (\(M) </th> <th style="text-align:center;"> Lim. Inf. 95% </th> <th style="text-align:center;"> Lim. Sup. 95% </th> <th style="text-align:center;"> Presupuesto (\)M) | Diferencia ($M) | |||
|---|---|---|---|---|---|
| Estrato 4 | 312.1 | 6.2 | 618.0 | 350 | -37.9 |
| Estrato 5 | 392.7 | 86.2 | 699.3 | 350 | 42.7 |
Interpretacion: El modelo estima $312.1M para estrato 4 y $392.7M para estrato 5. Los resultados son distintos entre estratos: para estrato 4, la prediccion de $312.1M es inferior al presupuesto de $350M, con un margen favorable de $37.9M, lo que hace viable la compra en este escenario. Sin embargo, el intervalo de prediccion al 95% es muy amplio ([$6.2M, $618.0M]), lo que indica alta incertidumbre en la estimacion puntual. Para estrato 5, la prediccion de $392.7M supera el presupuesto en $42.7M, aunque el limite inferior del IC95% ($86.2M) sugiere que podrian existir propiedades de ese perfil dentro del presupuesto. En resumen, una casa con las especificaciones solicitadas puede ser viable en estrato 4 pero ajustada, y es inviable en estrato 5 a precio de mercado tipico.
Sugiera potenciales ofertas que respondan a la solicitud de la vivienda 1 con credito preaprobado de maximo $350 millones. Presente al menos 5 ofertas en un mapa y discutalas.
Tabla 11. Top 5 ofertas — Casas Zona Norte dentro del presupuesto ($350M)
ofertas_v1 <- base1 %>%
filter(estrato %in% c(4,5), preciom <= 350,
habitaciones >= 4, banios >= 2, parqueaderos >= 1) %>%
arrange(preciom)
if (nrow(ofertas_v1) < 5) {
ofertas_v1 <- base1 %>%
filter(estrato %in% c(4,5), preciom <= 350) %>%
arrange(preciom) %>%
head(8)
}
cat("Ofertas encontradas dentro del presupuesto:", nrow(ofertas_v1), "\n")## Ofertas encontradas dentro del presupuesto: 60
ofertas_v1 %>%
dplyr::select(barrio, estrato, areaconst, habitaciones,
banios, parqueaderos, preciom) %>%
head(5) %>%
kable(digits=1, align="c",
col.names=c("Barrio","Estrato","Area (m2)","Habitaciones",
"Banos","Parqueaderos","Precio ($M)")) %>%
kable_styling(bootstrap_options=c("striped","hover","condensed"))| Barrio | Estrato | Area (m2) | Habitaciones | Banos | Parqueaderos | Precio ($M) |
|---|---|---|---|---|---|---|
| salomia | 4 | 100 | 4 | 4 | 1 | 220 |
| villa del sol | 4 | 73 | 4 | 3 | 1 | 223 |
| villa del sol | 4 | 73 | 4 | 3 | 1 | 223 |
| la merced | 4 | 250 | 5 | 3 | 2 | 230 |
| villa del sol | 4 | 82 | 4 | 3 | 1 | 240 |
Figura 9. Mapa interactivo de ofertas potenciales — Vivienda 1
top5_v1 <- ofertas_v1 %>% head(5)
popup_todas1 <- paste0(
"<b>Barrio:</b> ", base1$barrio, "<br>",
"<b>Estrato:</b> ", base1$estrato, "<br>",
"<b>Area:</b> ", base1$areaconst, " m2<br>",
"<b>Precio:</b> $", base1$preciom, "M"
)
popup_top1 <- paste0(
"<b>OFERTA RECOMENDADA</b><br>",
"<b>Barrio:</b> ", top5_v1$barrio, "<br>",
"<b>Estrato:</b> ", top5_v1$estrato, "<br>",
"<b>Area:</b> ", top5_v1$areaconst, " m2<br>",
"<b>Habitaciones:</b> ", top5_v1$habitaciones, "<br>",
"<b>Banos:</b> ", top5_v1$banios, "<br>",
"<b>Parqueaderos:</b> ", top5_v1$parqueaderos, "<br>",
"<b>Precio:</b> $", top5_v1$preciom, "M"
)
leaflet() %>%
addProviderTiles(providers$OpenStreetMap) %>%
setView(lng=-76.535, lat=3.470, zoom=13) %>%
addCircleMarkers(
data=base1, lng=~longitud, lat=~latitud,
radius=5, color="gray50", fillOpacity=0.4, stroke=FALSE,
popup=popup_todas1, group="Todas las casas"
) %>%
addCircleMarkers(
data=top5_v1, lng=~longitud, lat=~latitud,
radius=12, color="#c62828", fillColor="#ef5350",
fillOpacity=0.9, stroke=TRUE, weight=2,
popup=popup_top1, group="Ofertas recomendadas"
) %>%
addLayersControl(
overlayGroups=c("Todas las casas","Ofertas recomendadas"),
options=layersControlOptions(collapsed=FALSE)
) %>%
addLegend(position="bottomright",
colors=c("gray50","#ef5350"),
labels=c("Todas las casas","Ofertas dentro del presupuesto"),
title="Vivienda 1", opacity=0.9)Analisis de ofertas — Vivienda 1: El modelo con datos reales del paquete identifica 60 propiedades de estrato 4–5 con precio ≤ $350M en la Zona Norte, lo que contrasta con la escasez del fallback simulado. Las 5 mejores opciones se ubican en barrios como Salomia y Villa del Sol (estrato 4), con areas entre 73 y 250 m2 y precios desde $220M. Estas propiedades cumplen el criterio de 4 habitaciones y parqueadero, aunque la mayoria tiene areas inferiores a los 200 m2 solicitados. La oferta mas cercana al perfil requerido es la propiedad de 250 m2 en La Merced ($230M, 5 habitaciones, 3 banos, 2 parqueaderos), que supera el area solicitada al precio mas competitivo del mercado. El mapa permite visualizar la distribucion geografica de las 60 opciones disponibles (puntos grises) frente a las 5 recomendadas (puntos rojos). Se sugiere priorizar las propiedades con mayor area dentro del presupuesto y verificar el estado de conservacion antes de tomar la decision final.
Aplique el mismo procedimiento para apartamentos de la zona sur de la ciudad.
base2 <- vivienda %>%
filter(tipo == "Apartamento", zona == "Zona Sur")
cat("Total de registros en base2:", nrow(base2), "\n")## Total de registros en base2: 2787
Tabla 12. Primeros 3 registros — Apartamentos Zona Sur
base2 %>%
head(3) %>%
kable(digits=1, align="c") %>%
kable_styling(bootstrap_options=c("striped","hover","condensed"),
full_width=TRUE)| 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.5 | 3.4 |
| 698 | Zona Sur | 02 | 3 | 78 | 40 | 1 | 1 | 2 | Apartamento | aguablanca | -76.5 | 3.4 |
| 8199 | Zona Sur | NA | 6 | 875 | 194 | 2 | 5 | 3 | Apartamento | aguacatal | -76.6 | 3.5 |
Tabla 13. Verificacion de tipo de vivienda
kable(as.data.frame(table(Tipo=base2$tipo)), align="c") %>%
kable_styling(bootstrap_options="striped", full_width=FALSE)| Tipo | Freq |
|---|---|
| Apartamento | 2787 |
Tabla 14. Verificacion de zona
kable(as.data.frame(table(Zona=base2$zona)), align="c") %>%
kable_styling(bootstrap_options="striped", full_width=FALSE)| Zona | Freq |
|---|---|
| Zona Sur | 2787 |
Tabla 15. Distribucion por estrato — Apartamentos Zona Sur
kable(as.data.frame(table(Estrato=base2$estrato)), align="c") %>%
kable_styling(bootstrap_options="striped", full_width=FALSE)| Estrato | Freq |
|---|---|
| 3 | 201 |
| 4 | 1091 |
| 5 | 1033 |
| 6 | 462 |
Tabla 16. Estadisticas descriptivas del precio — Apartamentos Zona Sur (millones COP)
base2 %>%
summarise(
Minimo = min(preciom, na.rm=TRUE),
Q1 = quantile(preciom, 0.25, na.rm=TRUE),
Mediana = median(preciom, na.rm=TRUE),
Media = mean(preciom, na.rm=TRUE),
Q3 = quantile(preciom, 0.75, na.rm=TRUE),
Maximo = max(preciom, na.rm=TRUE),
Des.Est = sd(preciom, na.rm=TRUE)
) %>%
kable(digits=1, align="c") %>%
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE)| Minimo | Q1 | Mediana | Media | Q3 | Maximo | Des.Est |
|---|---|---|---|---|---|---|
| 75 | 175 | 245 | 297.3 | 335 | 1750 | 191.6 |
Figura 10. Mapa interactivo de ubicaciones — Apartamentos Zona Sur
pal2 <- colorFactor(
palette = c("4"="#1565C0","5"="#FF9800","6"="#6a1b9a"),
domain = as.character(base2$estrato)
)
leaflet(base2) %>%
addProviderTiles(providers$OpenStreetMap) %>%
setView(lng=-76.545, lat=3.375, zoom=13) %>%
addCircleMarkers(
lng=~longitud, lat=~latitud,
radius=7, color=~pal2(as.character(estrato)),
stroke=TRUE, weight=1, fillOpacity=0.85,
popup=~paste0(
"<b>Barrio:</b> ", barrio, "<br>",
"<b>Estrato:</b> ", estrato, "<br>",
"<b>Piso:</b> ", piso, "<br>",
"<b>Area:</b> ", areaconst, " m2<br>",
"<b>Precio:</b> $", preciom, "M"
)
) %>%
addLegend(position="bottomright", pal=pal2,
values=~as.character(estrato),
title="Estrato", opacity=0.9)Interpretacion — Mapa base2: Los 2,787 registros de apartamentos en la Zona Sur se distribuyen en la franja sur de Cali, cubriendo barrios como El Lido, Granada, San Fernando y Tequendama. La distribucion por estrato muestra predominancia de estrato 4 (1,091 apartamentos) y estrato 5 (1,033), seguidos de estrato 6 (462) y estrato 3 (201). El precio oscila entre $75M y $1,750M con una mediana de $245M y media de $297.3M. La alta concentracion de puntos en la zona permite visualizar claramente los clusters de precios por barrio. Algunos puntos pueden aparecer en zonas limitrofes por imprecision en los limites administrativos de la base de datos.
Analisis exploratorio con graficos interactivos
plotlypara apartamentos de la Zona Sur. Interprete los resultados.
Tabla 17. Matriz de correlaciones de Pearson — Apartamentos Zona Sur
vars_num2 <- base2 %>%
dplyr::select(preciom, areaconst, estrato, banios, habitaciones, parqueaderos)
cor_matrix2 <- round(cor(vars_num2, use="complete.obs"), 3)
kable(cor_matrix2, align="c") %>%
kable_styling(bootstrap_options=c("striped","hover","condensed"))| preciom | areaconst | estrato | banios | habitaciones | parqueaderos | |
|---|---|---|---|---|---|---|
| preciom | 1.000 | 0.741 | 0.650 | 0.711 | 0.296 | 0.693 |
| areaconst | 0.741 | 1.000 | 0.452 | 0.664 | 0.407 | 0.578 |
| estrato | 0.650 | 0.452 | 1.000 | 0.535 | 0.177 | 0.486 |
| banios | 0.711 | 0.664 | 0.535 | 1.000 | 0.520 | 0.556 |
| habitaciones | 0.296 | 0.407 | 0.177 | 0.520 | 1.000 | 0.237 |
| parqueaderos | 0.693 | 0.578 | 0.486 | 0.556 | 0.237 | 1.000 |
Figura 11. Precio vs. Area Construida por estrato — Apartamentos Zona Sur
plot_ly(
data=base2, x=~areaconst, y=~preciom,
color=~factor(estrato), colors=c("4"="#1565C0","5"="#FF9800","6"="#6a1b9a"),
type="scatter", mode="markers", marker=list(size=8, opacity=0.75),
text=~paste0("Barrio: ",barrio,"<br>Piso: ",piso,
"<br>Area: ",areaconst," m2<br>Precio: $",preciom,"M"),
hoverinfo="text"
) %>%
layout(
title=list(text="<b>Precio vs. Area Construida — Apartamentos Zona Sur</b>"),
xaxis=list(title="Area Construida (m2)"),
yaxis=list(title="Precio (millones $)"),
legend=list(title=list(text="<b>Estrato</b>"))
)Interpretacion: El area construida es el principal predictor del precio en apartamentos de la Zona Sur (r = 0.741), correlacion incluso superior a la observada en casas de la Zona Norte (r = 0.685). La relacion es positiva y relativamente lineal. Los colores por estrato muestran un desplazamiento vertical claro: apartamentos de estrato 6 de igual area se valoran significativamente por encima de los de estrato 4, capturando el efecto del entorno socioeconomico, la calidad del edificio y los servicios del conjunto residencial.
Figura 12. Precio vs. Numero de parqueaderos por estrato — Apartamentos Zona Sur
plot_ly(
data=base2, x=~factor(parqueaderos), y=~preciom,
color=~factor(estrato), colors=c("4"="#1565C0","5"="#FF9800","6"="#6a1b9a"),
type="box", boxpoints="outliers", hoverinfo="y"
) %>%
layout(
title=list(text="<b>Precio vs. Parqueaderos — Apartamentos Zona Sur</b>"),
xaxis=list(title="Numero de parqueaderos"),
yaxis=list(title="Precio (millones $)"),
legend=list(title=list(text="<b>Estrato</b>"))
)Interpretacion: Los parqueaderos son la tercera
variable con mayor correlacion con el precio en apartamentos (r =
0.693), muy por encima de lo observado en casas de la Zona Norte (r =
0.412). A medida que aumenta el numero de parqueaderos, la mediana del
precio sube de forma consistente en todos los estratos. Este resultado
refleja que en el mercado de apartamentos de la Zona Sur, el parqueadero
es un bien escaso y valorado. En el modelo de regresion,
parqueaderos resulta ser el predictor con el mayor
coeficiente absoluto ($72.91M por parqueadero adicional).
Figura 13. Heatmap de correlaciones — Apartamentos Zona Sur
cor_df2 <- as.data.frame(as.table(cor_matrix2))
names(cor_df2) <- c("Var1","Var2","Correlacion")
plot_ly(
data=cor_df2, x=~Var1, y=~Var2, z=~Correlacion,
type="heatmap",
colorscale=list(c(0,"#d32f2f"),c(0.5,"white"),c(1,"#1b5e20")),
zmin=-1, zmax=1,
hovertemplate="<b>%{x}</b> vs <b>%{y}</b><br>r = %{z:.3f}<extra></extra>"
) %>%
layout(
title=list(text="<b>Heatmap de Correlaciones — Apartamentos Zona Sur</b>"),
xaxis=list(title=""), yaxis=list(title="")
)Interpretacion general: En apartamentos de la Zona
Sur, areaconst lidera la correlacion con el precio (r =
0.741), seguida de banios (r = 0.711),
parqueaderos (r = 0.693), estrato (r = 0.650)
y habitaciones (r = 0.296). A diferencia de las casas,
todas las variables presentan correlaciones fuertes con el precio, lo
que anticipa que todas seran significativas en el modelo. Sin embargo,
destaca la alta correlacion entre predictores:
banios-areaconst (r = 0.664),
banios-parqueaderos (r = 0.556),
estrato-banios (r = 0.535), lo que podria
elevar los VIF aunque sin llegar al umbral problematico de 5.
Estimacion e interpretacion del modelo de regresion multiple para apartamentos de la Zona Sur.
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
Tabla 18. Coeficientes del modelo — Apartamentos Zona Sur (variables significativas resaltadas)
coefs2 <- as.data.frame(summary(modelo2)$coefficients)
coefs2$Sig <- ifelse(coefs2[,4]<0.001,"***",
ifelse(coefs2[,4]<0.01, "**",
ifelse(coefs2[,4]<0.05, "*",
ifelse(coefs2[,4]<0.1, ".", "NS"))))
names(coefs2)[1:4] <- c("Estimado","Error Std.","Estadistico t","p-valor")
kable(coefs2, digits=4, align="c") %>%
kable_styling(bootstrap_options=c("striped","hover","condensed")) %>%
row_spec(which(coefs2$`p-valor` < 0.05),
bold=TRUE, color="white", background="#6a1b9a")| Estimado | Error Std. | Estadistico t | p-valor | Sig | |
|---|---|---|---|---|---|
| (Intercept) | -261.6250 | 15.6322 | -16.7363 | 0 | *** |
| areaconst | 1.2850 | 0.0540 | 23.7853 | 0 | *** |
| estrato | 60.8971 | 3.0841 | 19.7457 | 0 | *** |
| habitaciones | -24.8369 | 3.8923 | -6.3811 | 0 | *** |
| parqueaderos | 72.9147 | 3.9580 | 18.4223 | 0 | *** |
| banios | 50.6967 | 3.3964 | 14.9267 | 0 | *** |
Tabla 19. Factores de Inflacion de Varianza (VIF) — Modelo 2
kable(as.data.frame(vif(modelo2)), col.names="VIF", digits=3, align="c") %>%
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE)| VIF | |
|---|---|
| areaconst | 2.067 |
| estrato | 1.545 |
| habitaciones | 1.429 |
| parqueaderos | 1.738 |
| banios | 2.529 |
Interpretacion de coeficientes — Modelo 2:
En apartamentos de la Zona Sur todas las variables son estadisticamente significativas (p < 0.001), con el mejor nivel de significancia global del analisis:
areaconst (β = 1.2850, ***): Cada
m2 adicional agrega $1.29M al precio (t = 23.785, p
< 2e-16). Mayor que en casas en terminos del coeficiente, aunque la
interpretacion es similar: el area es el predictor con mayor
significancia estadistica del modelo.
parqueaderos (β = 72.9147, ***):
Cada parqueadero adicional agrega $72.91M al precio (t
= 18.422, p < 2e-16). Es el coeficiente de mayor
magnitud del modelo y el mas destacable: en el mercado de
apartamentos de la Zona Sur, un parqueadero vale mas del doble que en
casas de la Zona Norte ($24M). Esto refleja la alta escasez y demanda de
parqueo en este segmento.
estrato (β = 60.8971, ***): Cada
nivel de estrato agrega $60.90M (t = 19.746, p <
2e-16). El efecto del estrato es comparable al observado en casas
($80.63M) y muy superior a lo que mostraba el fallback simulado,
capturando la diferencia de calidad entre conjuntos residenciales de
distintos estratos en la Zona Sur.
banios (β = 50.6967, ***): Cada
bano adicional agrega $50.70M (t = 14.927, p <
2e-16). Es un diferenciador clave en apartamentos, donde los banos
adicionales indican mayor lujo y amplitud, a diferencia de las casas
donde no fue significativo.
habitaciones (β = -24.8369, ***):
Cada habitacion adicional REDUCE el precio en $24.84M
(t = -6.381, p = 2.11e-10). Este coeficiente negativo es contraintuitivo
pero estadisticamente robusto. La explicacion es la multicolinealidad
parcial: una vez controladas area, banos y parqueaderos, tener mas
habitaciones implica habitaciones mas pequenas, lo que se penaliza en el
mercado. Un apartamento de igual area con mas habitaciones tiene cuartos
mas estrechos, percibidos como menos deseables.
R² = 0.7485 (R² ajustado = 0.7480): El modelo explica el 74.9% de la variabilidad del precio, con un error estandar residual de $98.02M. Es el mejor ajuste de los dos modelos, con 406 observaciones eliminadas por NA. El 25.1% restante refleja variables no capturadas: piso del apartamento, antiguedad del edificio, amenidades del conjunto (piscina, gimnasio, vigilancia) y calidad de los acabados.
Multicolinealidad: Los VIF oscilan entre 1.429 (habitaciones) y 2.529 (banios), todos por debajo del umbral de 5. No existe multicolinealidad problematica, aunque los valores de banios (2.529) y areaconst (2.067) son los mas elevados, coherente con su alta correlacion bivariada (r = 0.664).
Validacion formal de los supuestos del modelo de apartamentos. Interprete y sugiera acciones correctivas si aplica.
Figura 14. Graficos de diagnostico del modelo — Apartamentos Zona Sur
Figura 15. Histograma de residuos con curva normal teorica — Modelo 2
res2 <- residuals(modelo2)
data.frame(residuos=res2) %>%
ggplot(aes(x=residuos)) +
geom_histogram(aes(y=after_stat(density)), bins=15,
fill="#6a1b9a", color="white", alpha=0.8) +
stat_function(fun=dnorm, args=list(mean=0, sd=sd(res2)),
color="#c62828", linewidth=1.2) +
labs(x="Residuos", y="Densidad") +
theme_minimal(base_size=13)Tabla 20. Pruebas formales de supuestos — Modelo 2
sw2 <- shapiro.test(res2)
bp2 <- bptest(modelo2)
dw2 <- dwtest(modelo2)
data.frame(
Supuesto = c("Normalidad de residuos (Shapiro-Wilk)",
"Homocedasticidad (Breusch-Pagan)",
"Autocorrelacion (Durbin-Watson)"),
Estadistico = round(c(sw2$statistic, bp2$statistic, dw2$statistic), 4),
p.valor = round(c(sw2$p.value, bp2$p.value, dw2$p.value), 4),
Conclusion = c(
ifelse(sw2$p.value>0.05,"Cumple (p > 0.05)","No cumple (p <= 0.05)"),
ifelse(bp2$p.value>0.05,"Cumple (p > 0.05)","No cumple (p <= 0.05)"),
ifelse(dw2$p.value>0.05,"Cumple (p > 0.05)","Indicio (p <= 0.05)")
)
) %>%
kable(align="c") %>%
kable_styling(bootstrap_options=c("striped","hover"))| Supuesto | Estadistico | p.valor | Conclusion | |
|---|---|---|---|---|
| W | Normalidad de residuos (Shapiro-Wilk) | 0.7912 | 0 | No cumple (p <= 0.05) |
| BP | Homocedasticidad (Breusch-Pagan) | 754.8051 | 0 | No cumple (p <= 0.05) |
| DW | Autocorrelacion (Durbin-Watson) | 1.5333 | 0 | Indicio (p <= 0.05) |
kable(as.data.frame(vif(modelo2)), col.names="VIF", digits=3, align="c") %>%
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE)| VIF | |
|---|---|
| areaconst | 2.067 |
| estrato | 1.545 |
| habitaciones | 1.429 |
| parqueaderos | 1.738 |
| banios | 2.529 |
Figura 16. Valores reales vs. predichos — Modelo 2
df_pred_m2 <- data.frame(
real = modelo2$model$preciom,
pred = fitted(modelo2)
)
ggplot(df_pred_m2, aes(x=pred, y=real)) +
geom_point(color="#6a1b9a", alpha=0.7, size=2.5) +
geom_abline(intercept=0, slope=1, color="#c62828",
linetype="dashed", linewidth=1) +
labs(x="Precio Predicho (M$)", y="Precio Real (M$)") +
theme_minimal(base_size=13)Interpretacion de supuestos — Modelo 2:
Normalidad (Shapiro-Wilk W = 0.7912, p < 0.001): Se rechaza H0 (p ≤ 0.05). Los residuos NO siguen distribucion normal. El estadistico W = 0.791 indica una desviacion severa de la normalidad, mayor que en el Modelo 1 (W = 0.853). El histograma muestra colas pesadas y posible asimetria, producto de la alta variabilidad de precios en una base de 2,787 apartamentos con valores desde $75M hasta $1,750M.
Homocedasticidad (Breusch-Pagan BP = 754.81, p < 0.001): Se rechaza H0 (p ≤ 0.05). Existe heterocedasticidad severa, con un estadistico BP muy superior al del Modelo 1 (80.28). La varianza de los residuos aumenta marcadamente con los valores ajustados: los apartamentos de alto precio presentan errores de prediccion mucho mayores que los de bajo precio. Esto es esperable en un mercado tan heterogeneo (2,787 observaciones en estratos 3 a 6).
Autocorrelacion (Durbin-Watson = 1.5333, p < 0.001): Se detecta autocorrelacion positiva significativa. El estadistico DW = 1.53 esta cerca del limite inferior del rango aceptable (1.5), y el p-valor confirma que los residuos no son independientes. Esto sugiere dependencia espacial entre propiedades vecinas en la Zona Sur.
Conclusion: Ambos modelos presentan los mismos
problemas: no normalidad, heterocedasticidad y autocorrelacion. Esto no
invalida la utilidad predictiva de los modelos, pero si afecta la
validez de los intervalos de confianza y los p-valores reportados.
Sugerencias de correccion: (1) Transformacion
logaritmica log(preciom) para estabilizar la varianza y
mejorar la normalidad. (2) Errores estandar robustos tipo HC3. (3)
Modelos GWR o SAR para capturar la dependencia espacial. (4) Incluir
efectos fijos de barrio. (5) Regresion por cuantiles como alternativa no
parametrica.
Con el modelo identificado, prediga el precio de la vivienda con las caracteristicas de la segunda solicitud.
Las caracteristicas de la Vivienda 2 son: area = 300 m2, estrato 5 o 6, 5 habitaciones, 3 parqueaderos, 3 banos, Zona Sur, tipo Apartamento.
Tabla 21. Prediccion del precio — Vivienda 2 (millones COP)
v2_e5 <- data.frame(areaconst=300, estrato=5, habitaciones=5,
parqueaderos=3, banios=3)
v2_e6 <- data.frame(areaconst=300, estrato=6, habitaciones=5,
parqueaderos=3, banios=3)
pred2_e5 <- predict(modelo2, newdata=v2_e5, interval="prediction", level=0.95)
pred2_e6 <- predict(modelo2, newdata=v2_e6, interval="prediction", level=0.95)
data.frame(
Escenario = c("Estrato 5","Estrato 6"),
Prediccion = round(c(pred2_e5[1], pred2_e6[1]), 1),
Lim.Inf.95 = round(c(pred2_e5[2], pred2_e6[2]), 1),
Lim.Sup.95 = round(c(pred2_e5[3], pred2_e6[3]), 1),
Presupuesto = 850,
Margen = round(c(850-pred2_e5[1], 850-pred2_e6[1]), 1)
) %>%
kable(align="c",
col.names=c("Escenario","Prediccion ($M)","Lim. Inf. 95%",
"Lim. Sup. 95%","Presupuesto ($M)","Margen ($M)")) %>%
kable_styling(bootstrap_options=c("striped","hover")) %>%
row_spec(1:2, bold=TRUE, color="white", background="#2e7d32")| Escenario | Prediccion (\(M) </th> <th style="text-align:center;"> Lim. Inf. 95% </th> <th style="text-align:center;"> Lim. Sup. 95% </th> <th style="text-align:center;"> Presupuesto (\)M) | Margen ($M) | |||
|---|---|---|---|---|---|
| Estrato 5 | 675.0 | 481.5 | 868.6 | 850 | 175.0 |
| Estrato 6 | 735.9 | 542.3 | 929.5 | 850 | 114.1 |
Interpretacion: El modelo estima $675.0M para estrato 5 y $735.9M para estrato 6. Para estrato 5, la prediccion esta dentro del presupuesto con un margen de $175M, y el limite superior del IC95% ($868.6M) apenas supera el techo de $850M, lo que indica que el presupuesto es suficiente con alta probabilidad. Para estrato 6, la prediccion de $735.9M tiene un margen de $114.1M, pero el limite superior del IC95% es $929.5M, el cual supera el presupuesto en $79.5M. Esto implica que en estrato 6 existe un riesgo estadistico de que la propiedad especifica encontrada supere el credito preaprobado. Se recomienda priorizar la busqueda en estrato 5, donde el IC95% es mas favorable, y negociar un techo de $850M como condicion de compra.
Sugiera potenciales ofertas para la vivienda 2 con credito preaprobado de $850 millones. Presente al menos 5 ofertas en un mapa y discutalas.
Tabla 22. Top 5 ofertas — Apartamentos Zona Sur dentro del presupuesto ($850M)
base2$pred_precio <- predict(modelo2, newdata=base2)
ofertas_v2 <- base2 %>%
filter(estrato %in% c(5,6), preciom <= 850,
habitaciones >= 5, banios >= 3, parqueaderos >= 3) %>%
arrange(desc(areaconst))
if (nrow(ofertas_v2) < 5) {
ofertas_v2 <- base2 %>%
filter(estrato %in% c(5,6), preciom <= 850) %>%
arrange(desc(areaconst)) %>%
head(8)
}
cat("Ofertas encontradas dentro del presupuesto:", nrow(ofertas_v2), "\n")## Ofertas encontradas dentro del presupuesto: 8
ofertas_v2 %>%
dplyr::select(barrio, estrato, areaconst, habitaciones,
banios, parqueaderos, preciom) %>%
head(5) %>%
kable(digits=1, align="c",
col.names=c("Barrio","Estrato","Area (m2)","Habitaciones",
"Banos","Parqueaderos","Precio ($M)")) %>%
kable_styling(bootstrap_options=c("striped","hover","condensed"))| Barrio | Estrato | Area (m2) | Habitaciones | Banos | Parqueaderos | Precio ($M) |
|---|---|---|---|---|---|---|
| valle del lili | 5 | 932 | 3 | 3 | 1 | 299 |
| el limonar | 5 | 605 | 2 | 2 | 1 | 170 |
| el ingenio | 5 | 600 | 5 | 4 | 2 | 650 |
| guadalupe | 5 | 573 | 5 | 8 | 3 | 730 |
| el ingenio | 5 | 486 | 4 | 4 | 2 | 690 |
Figura 17. Mapa interactivo de ofertas potenciales — Vivienda 2
top5_v2 <- ofertas_v2 %>% head(5)
popup_todas2 <- paste0(
"<b>Barrio:</b> ", base2$barrio, "<br>",
"<b>Estrato:</b> ", base2$estrato, "<br>",
"<b>Area:</b> ", base2$areaconst, " m2<br>",
"<b>Precio:</b> $", base2$preciom, "M"
)
popup_top2 <- paste0(
"<b>OFERTA RECOMENDADA</b><br>",
"<b>Barrio:</b> ", top5_v2$barrio, "<br>",
"<b>Estrato:</b> ", top5_v2$estrato, "<br>",
"<b>Piso:</b> ", top5_v2$piso, "<br>",
"<b>Area:</b> ", top5_v2$areaconst, " m2<br>",
"<b>Habitaciones:</b> ", top5_v2$habitaciones, "<br>",
"<b>Banos:</b> ", top5_v2$banios, "<br>",
"<b>Parqueaderos:</b> ", top5_v2$parqueaderos, "<br>",
"<b>Precio:</b> $", top5_v2$preciom, "M"
)
leaflet() %>%
addProviderTiles(providers$OpenStreetMap) %>%
setView(lng=-76.545, lat=3.375, zoom=13) %>%
addCircleMarkers(
data=base2, lng=~longitud, lat=~latitud,
radius=5, color="gray50", fillOpacity=0.4, stroke=FALSE,
popup=popup_todas2, group="Todos los apartamentos"
) %>%
addCircleMarkers(
data=top5_v2, lng=~longitud, lat=~latitud,
radius=12, color="#4a148c", fillColor="#8e24aa",
fillOpacity=0.9, stroke=TRUE, weight=2,
popup=popup_top2, group="Ofertas recomendadas"
) %>%
addLayersControl(
overlayGroups=c("Todos los apartamentos","Ofertas recomendadas"),
options=layersControlOptions(collapsed=FALSE)
) %>%
addLegend(position="bottomright",
colors=c("gray50","#8e24aa"),
labels=c("Todos los aptos","Ofertas dentro del presupuesto"),
title="Vivienda 2", opacity=0.9)Analisis de ofertas — Vivienda 2: El codigo encuentra 8 propiedades que cumplen todos los criterios (estrato 5–6, preciom ≤ $850M, habitaciones ≥ 5, banos ≥ 3, parqueaderos ≥ 3). Las 5 mejores opciones por mayor area se ubican en barrios consolidados de estrato 5 como Valle del Lili, El Limonar, El Ingenio y Guadalupe. Destaca la propiedad en Guadalupe (573 m2, 5 habitaciones, 8 banos, 3 parqueaderos, $730M) como la opcion que mejor combina area amplia y parqueaderos suficientes dentro del presupuesto. La opcion en El Ingenio ($650M, 600 m2, 5 habitaciones, 4 banos, 2 parqueaderos) tiene el mayor area pero solo 2 parqueaderos, un parqueadero menos del solicitado. Se recomienda priorizar la propiedad en Guadalupe como primera opcion y la de El Ingenio como segunda si el cliente acepta flexibilizar el numero de parqueaderos. Antes de tomar la decision final verificar los costos de administracion mensual del conjunto residencial, que en estrato 5–6 pueden oscilar entre $1.5M y $3M mensuales.
Tabla 23. Resumen ejecutivo comparativo — Ambas solicitudes
data.frame(
Vivienda = c("Vivienda 1 — Casa Zona Norte",
"Vivienda 2 — Apartamento Zona Sur"),
Precio.Estimado = c("$312.1M (e4) / $392.7M (e5)", "$675.0M (e5) / $735.9M (e6)"),
Presupuesto = c("$350M", "$850M"),
Viable = c("Parcial — viable en estrato 4 (+$37.9M); inviable en estrato 5 (-$42.7M)",
"Viable en e5 (margen $175M); e6 con riesgo IC95% hasta $929.5M"),
Variables.Sig = c("areaconst***, estrato***, parqueaderos***, banios*; habitaciones NS",
"Todas ***; habitaciones*** (efecto NEGATIVO: -$24.84M/hab)"),
R2 = c("60.4%", "74.9%")
) %>%
kable(align="c",
col.names=c("Vivienda","Precio Estimado","Presupuesto",
"Viabilidad","Variables Significativas","R2")) %>%
kable_styling(bootstrap_options=c("striped","hover","condensed"))| Vivienda | Precio Estimado | Presupuesto | Viabilidad | Variables Significativas | R2 |
|---|---|---|---|---|---|
| Vivienda 1 — Casa Zona Norte | $312.1M (e4) / $392.7M (e5) | $350M | Parcial — viable en estrato 4 (+$37.9M); inviable en estrato 5 (-$42.7M) | areaconst, estrato, parqueaderos**, banios; habitaciones NS | 60.4% |
| Vivienda 2 — Apartamento Zona Sur | $675.0M (e5) / $735.9M (e6) | $850M | Viable en e5 (margen $175M); e6 con riesgo IC95% hasta $929.5M | Todas ; habitaciones (efecto NEGATIVO: -$24.84M/hab) | 74.9% |
Los dos modelos de regresion lineal multiple estimados permiten extraer las siguientes conclusiones generales:
Determinantes del precio en casas (Zona Norte). El modelo sobre 435 observaciones validas (de 722 totales) explica el 60.4% de la variabilidad del precio con R² = 0.604. El estrato socioeconomico tiene el mayor impacto absoluto con $80.63M por nivel (t = 8.206), seguido por parqueaderos ($24.01M, t = 4.090), banios ($18.90M, t = 2.524) y area ($0.677M/m2, t = 12.814). Las habitaciones no resultaron significativas (p = 0.177), pues su efecto queda absorbido por las demas variables. El error estandar residual de $155.1M refleja la alta heterogeneidad de precios en esta zona (rango $89M–$1,940M).
Determinantes del precio en apartamentos (Zona Sur).
El modelo sobre 2,381 observaciones validas explica el 74.9% de
la variabilidad del precio con R² = 0.7485, el mejor ajuste.
Los parqueaderos tienen el coeficiente de mayor magnitud
($72.91M, t = 18.422), seguidos por estrato
($60.90M, t = 19.746), banios
($50.70M, t = 14.927) y area
($1.285M/m2, t = 23.785). El hallazgo mas relevante es
que habitaciones presenta un coeficiente negativo
significativo (-$24.84M, t = -6.381): controladas el area,
banos y parqueaderos, mas habitaciones implica cuartos mas pequenos,
penalizando el precio en el mercado.
Cumplimiento de supuestos. Ambos modelos incumplen los supuestos de normalidad (Shapiro-Wilk p < 0.001 en ambos) y homocedasticidad (Breusch-Pagan p < 0.001 en ambos), y presentan indicios de autocorrelacion (DW M1 = 1.7615 p = 0.0055; DW M2 = 1.5333 p < 0.001). Esto no invalida las predicciones puntuales, pero si afecta la precision de los intervalos de confianza reportados. Se recomienda aplicar transformacion logaritmica al precio y errores estandar robustos para corregir estos problemas. La multicolinealidad no es problematica en ninguno de los dos modelos (VIF maximos: 1.967 en M1 y 2.529 en M2).
Vivienda 1 — Casa Zona Norte. El resultado es parcialmente viable. Para estrato 4, el modelo estima $312.1M, dentro del presupuesto con un margen de $37.9M, y la base real contiene 60 propiedades de estrato 4–5 con precio ≤ $350M. Sin embargo, el IC95% muy amplio ([$6.2M, $618.0M]) refleja la alta incertidumbre del modelo en este segmento, producto del incumplimiento de homocedasticidad. Para estrato 5, el precio estimado de $392.7M supera el presupuesto en $42.7M. Se recomienda orientar la busqueda hacia propiedades de estrato 4 en barrios como Salomia o Villa del Sol, donde existen 60 opciones reales a precio competitivo. Si el cliente requiere estrato 5 con 200 m2, deberia ampliar el credito a aproximadamente $393M.
Vivienda 2 — Apartamento Zona Sur. La solicitud es viable principalmente en estrato 5. El modelo estima $675.0M con margen de $175M sobre el presupuesto de $850M, y el IC95% [$481.5M, $868.6M] se mantiene practicamente dentro del techo. Para estrato 6 ($735.9M), el IC95% superior de $929.5M supera el presupuesto en $79.5M, introduciendo riesgo estadistico. El mercado ofrece 8 propiedades que cumplen todos los criterios solicitados simultaneamente (estrato 5–6, ≤ $850M, ≥ 5 habitaciones, ≥ 3 banos, ≥ 3 parqueaderos). La mejor opcion identificada es un apartamento en Guadalupe (573 m2, $730M, estrato 5) con un margen comodo de $120M para gastos transaccionales.