Introducción

El presente informe detalla el análisis de datos y la construcción de modelos de regresión lineal múltiple para la valoración de inmuebles en la ciudad de Cali. El objetivo es brindar recomendaciones basadas en datos para la adquisición de dos viviendas específicas solicitadas por una compañía internacional, optimizando el presupuesto preaprobado de $350 millones y $850 millones, respectivamente.


PARTE 1: Análisis Vivienda 1 (Casas, Zona Norte)

Requerimientos de la Solicitud 1: Casa, Zona Norte, 200 m² construidos, 1 parqueadero, 2 baños, 4 habitaciones, Estrato 4 o 5. Presupuesto: 350 Millones.

Paso 1: Filtro Inicial y Depuración

# Filtro de datos y limpieza de valores ausentes
df_norte <- vivienda %>%
  filter(tipo == "Casa", zona == "Zona Norte") %>%
  drop_na(preciom, areaconst, estrato, banios, habitaciones, parqueaderos, longitud, latitud) %>%
  mutate(estrato = as.numeric(estrato),
         parqueaderos = as.numeric(parqueaderos)) %>%
  # Limpieza de valores atípicos espaciales (Cali)
  filter(longitud > -76.6 & longitud < -76.4, latitud > 3.3 & latitud < 3.5)

# Presentación de los primeros 3 registros
df_norte %>%
  head(3) %>%
  select(barrio, preciom, areaconst, estrato, habitaciones) %>%
  kbl(caption = "Tabla 1: Primeros 3 registros - Casas Zona Norte") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Tabla 1: Primeros 3 registros - Casas Zona Norte
barrio preciom areaconst estrato habitaciones
acopi 320 150 5 6
acopi 780 380 5 3
acopi 625 355 4 5
# Mapa de puntos espaciales
leaflet(df_norte) %>%
  addProviderTiles(providers$OpenStreetMap) %>%
  addCircleMarkers(~longitud, ~latitud, radius = 3, color = "#0073C2", fillOpacity = 0.5,
                   popup = ~paste("Precio:", preciom, "M<br>Área:", areaconst, "m2"))

Discusión del Mapa: La visualización confirma que la oferta de casas filtradas se ubica de forma correcta en el clúster de la Zona Norte de Cali. Los puntos que aparecen ligeramente dispersos en los límites de la zona suelen deberse a la imputación automática de coordenadas (geocodificación) que realizan los portales inmobiliarios a partir del nombre del barrio, lo cual introduce un margen de error espacial normal en estos conjuntos de datos.

Paso 2: Análisis Exploratorio de Datos (EDA)

# 1. Matriz de correlación
vars_numericas <- df_norte %>% select(preciom, areaconst, estrato, banios, habitaciones)
M <- cor(vars_numericas)
corrplot(M, method = "ellipse", type = "upper", tl.col = "black", tl.srt = 45, 
         addCoef.col = "black", diag = FALSE, title = "Correlación de Variables (Norte)", mar=c(0,0,1,0))

# 2. Gráfico Interactivo con Plotly
p <- ggplot(df_norte, aes(x = areaconst, y = preciom, color = as.factor(estrato), size = habitaciones)) +
  geom_point(alpha = 0.6) +
  labs(title = "Precio vs Área Construida (Norte)", x = "Área Construida (m2)", y = "Precio (M)", color = "Estrato") +
  theme_light()
ggplotly(p)

Interpretación de Resultados: Se evidencia una correlación positiva y fuerte (0.69) entre el área construida y el precio de la vivienda. Adicionalmente, el gráfico interactivo demuestra que el estrato actúa como un factor de incremento (las propiedades de estrato 5 se ubican sistemáticamente en una franja de precios superior a las de estrato 4 para la misma área).

Paso 3: Estimación del Modelo de Regresión

Se plantea un modelo \(Precio = \beta_0 + \beta_1(Área) + \beta_2(Estrato) + \dots + \epsilon\).

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

# Resumen de coeficientes
coeficientes <- as.data.frame(summary(modelo_norte)$coefficients)
kbl(coeficientes, digits = 3, caption = "Tabla 2: Coeficientes del Modelo - Casas Norte") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 2: Coeficientes del Modelo - Casas Norte
Estimate Std. Error t value Pr(>|t|)
(Intercept) -238.171 44.406 -5.364 0.000
areaconst 0.677 0.053 12.814 0.000
estrato 80.635 9.826 8.206 0.000
habitaciones 7.645 5.659 1.351 0.177
parqueaderos 24.006 5.869 4.090 0.000
banios 18.899 7.488 2.524 0.012

Interpretación: Todos los coeficientes (excepto quizá habitaciones, dependiendo del p-valor) son estadísticamente significativos. El coeficiente de areaconst indica cuántos millones de pesos aumenta el precio del inmueble por cada metro cuadrado adicional, manteniendo las demás variables constantes. El \(R^2\) ajustado del modelo nos indica el nivel de ajuste global; para mejorarlo, sería recomendable incluir la edad de la casa o la distancia a avenidas principales.

Paso 4: Validación de Supuestos del Modelo

# Multicolinealidad
vif_valores <- vif(modelo_norte)

# Homocedasticidad
bp_test <- bptest(modelo_norte)

# Normalidad
shapiro_test <- shapiro.test(sample(modelo_norte$residuals, 5000, replace = TRUE))

data.frame(
  Prueba = c("Breusch-Pagan (Homocedasticidad)", "Shapiro-Wilk (Normalidad)"),
  Estadistico = c(bp_test$statistic, shapiro_test$statistic),
  P_Valor = c(bp_test$p.value, shapiro_test$p.value)
) %>%
  kbl(caption = "Tabla 3: Pruebas de Supuestos Estadísticos") %>%
  kable_styling(full_width = FALSE)
Tabla 3: Pruebas de Supuestos Estadísticos
Prueba Estadistico P_Valor
BP Breusch-Pagan (Homocedasticidad) 80.2808348 0
W Shapiro-Wilk (Normalidad) 0.8441664 0

Interpretación: Es frecuente que los modelos de valoración inmobiliaria presenten problemas de heterocedasticidad (p-valor < 0.05 en Breusch-Pagan), ya que las casas más costosas tienen una varianza de precios mucho mayor. Se sugiere, para futuras iteraciones, utilizar estimadores de varianza robustos o transformar la variable dependiente. Los valores VIF indican que, aunque las casas más grandes tienen más baños, la colinealidad es manejable.

Paso 5: Predicción Puntual

# Datos de la vivienda solicitada
solicitud1 <- data.frame(areaconst = 200, estrato = 4, habitaciones = 4, parqueaderos = 1, banios = 2)

# Predicción
pred_1 <- predict(modelo_norte, newdata = solicitud1, interval = "confidence")

kbl(pred_1, digits = 2, caption = "Tabla 4: Predicción de Precio (Millones COP)") %>%
  kable_styling(bootstrap_options = "bordered", full_width = FALSE)
Tabla 4: Predicción de Precio (Millones COP)
fit lwr upr
312.1 287.19 337.01

Análisis: El modelo estima un valor promedio para una vivienda con estas características exactas. Este valor sirve como ancla para evaluar si los $350 millones preaprobados por la empresa son suficientes frente a la realidad del mercado en la Zona Norte.

Paso 6: Potenciales Ofertas (Max 350 Millones)

ofertas1 <- df_norte %>%
  filter(preciom <= 350, areaconst >= 180, habitaciones >= 3, parqueaderos >= 1) %>%
  arrange(desc(areaconst)) %>%
  head(5)

leaflet(ofertas1) %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addAwesomeMarkers(~longitud, ~latitud, 
                    popup = ~paste("<b>Barrio:</b>", barrio, "<br><b>Precio:</b>", preciom, "M<br><b>Área:</b>", areaconst, "m2"))

Discusión: Se presentan 5 inmuebles reales filtrados de la base de datos que cumplen estrictamente con el techo de $350 millones. Estas opciones maximizan el área construida (buscando acercarse a los 200 m² solicitados). Se sugiere a la empresa visitar estos inmuebles.


PARTE 2: Análisis Vivienda 2 (Apartamentos, Zona Sur)

Requerimientos de la Solicitud 2: Apartamento, Zona Sur, 300 m² construidos, 3 parqueaderos, 3 baños, 5 habitaciones, Estrato 5 o 6. Presupuesto: 850 Millones.

Paso 1: Filtro Inicial y Depuración

df_sur <- vivienda %>%
  filter(tipo == "Apartamento", zona == "Zona Sur") %>%
  drop_na(preciom, areaconst, estrato, banios, habitaciones, parqueaderos, longitud, latitud) %>%
  mutate(estrato = as.numeric(estrato), parqueaderos = as.numeric(parqueaderos)) %>%
  filter(longitud > -76.6 & longitud < -76.4, latitud > 3.3 & latitud < 3.5)

df_sur %>% head(3) %>% select(barrio, preciom, areaconst, estrato, parqueaderos) %>%
  kbl(caption = "Tabla 5: Primeros 3 registros - Aptos Zona Sur") %>% kable_styling(full_width = FALSE)
Tabla 5: Primeros 3 registros - Aptos Zona Sur
barrio preciom areaconst estrato parqueaderos
acopi 290 96 4 1
aguablanca 78 40 3 1
aguacatal 875 194 6 2
leaflet(df_sur) %>% addProviderTiles(providers$OpenStreetMap) %>%
  addCircleMarkers(~longitud, ~latitud, radius = 3, color = "#E74C3C", fillOpacity = 0.5)

Paso 2: Análisis Exploratorio de Datos (EDA)

p2 <- ggplot(df_sur, aes(x = areaconst, y = preciom, color = as.factor(estrato))) +
  geom_point(alpha = 0.5) +
  geom_smooth(method = "lm", se = FALSE, color = "black", linetype = "dashed") +
  labs(title = "Precio vs Área Construida (Sur)", x = "Área (m2)", y = "Precio (M)", color = "Estrato") +
  theme_light()
ggplotly(p2)

Interpretación: En el segmento de apartamentos del sur, la varianza de los precios aumenta drásticamente para áreas grandes. Un apartamento de 300 m² pertenece a la categoría de lujo, donde los precios escalan de forma pronunciada.

Paso 3: Estimación del Modelo de Regresión

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

kbl(as.data.frame(summary(modelo_sur)$coefficients), digits = 3, caption = "Tabla 6: Coeficientes - Aptos Sur") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 6: Coeficientes - Aptos Sur
Estimate Std. Error t value Pr(>|t|)
(Intercept) -261.625 15.632 -16.736 0
areaconst 1.285 0.054 23.785 0
estrato 60.897 3.084 19.746 0
habitaciones -24.837 3.892 -6.381 0
parqueaderos 72.915 3.958 18.422 0
banios 50.697 3.396 14.927 0

Interpretación: En apartamentos de estrato alto, la variable parqueaderos tiene una significancia e impacto monetario considerable, dada la escasez de espacio en unidades residenciales verticales.

Paso 4: Validación de Supuestos

data.frame(
  Prueba = c("Breusch-Pagan (Homocedasticidad)", "Shapiro-Wilk (Normalidad)"),
  P_Valor = c(bptest(modelo_sur)$p.value, shapiro.test(sample(modelo_sur$residuals, 5000, replace = TRUE))$p.value)
) %>% kbl(caption = "Tabla 7: Pruebas de Supuestos") %>% kable_styling(full_width = FALSE)
Tabla 7: Pruebas de Supuestos
Prueba P_Valor
BP Breusch-Pagan (Homocedasticidad) 0
Shapiro-Wilk (Normalidad) 0

Paso 5: Predicción Puntual

solicitud2 <- data.frame(areaconst = 300, estrato = 6, habitaciones = 5, parqueaderos = 3, banios = 3)
pred_2 <- predict(modelo_sur, newdata = solicitud2, interval = "confidence")

kbl(pred_2, digits = 2, caption = "Tabla 8: Predicción de Precio (Apto Sur)") %>%
  kable_styling(bootstrap_options = "bordered", full_width = FALSE)
Tabla 8: Predicción de Precio (Apto Sur)
fit lwr upr
735.92 712.72 759.12

Paso 6: Potenciales Ofertas (Max 850 Millones)

ofertas2 <- df_sur %>%
  filter(preciom <= 850, areaconst >= 250, parqueaderos >= 2, habitaciones >= 4) %>%
  arrange(desc(areaconst)) %>%
  head(5)

leaflet(ofertas2) %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addAwesomeMarkers(~longitud, ~latitud, 
                    popup = ~paste("<b>Barrio:</b>", barrio, "<br><b>Precio:</b>", preciom, "M<br><b>Área:</b>", areaconst, "m2"))

Discusión: Los 850 millones preaprobados permiten acceder a propiedades muy exclusivas en la Zona Sur. Se mapearon 5 apartamentos que, si bien pueden estar ligeramente por debajo de los 300 m², cumplen con las altas exigencias de amenidades (parqueaderos y habitaciones) que requiere el cliente.