Maria comenzó como agente de bienes raíces en Cali hace 10 años. Después de laborar dos años para una empresa nacional, se traslado a Bogotá y trabajó para otra agencia de bienes raíces. Sus amigos y familiares la convencieron de que con su experiencia y conocimientos del negocio debía abrir su propia agencia. Terminó por adquirir la licencia de intermediario y al poco tiempo fundó su propia compañía, C&A (Casas y Apartamentos) en Cali. Santiago y Lina, dos vendedores de la empresa anterior aceptaron trabajar en la nueva compaña. En la actualidad ocho agentes de bienes raíces colaboran con ella en C&A.
Actualmente las ventas de bienes raíces en Cali se han visto disminuidas de manera significativa en lo corrido del año. Durante este periodo muchas instituciones bancarias de ahorro y vivienda están prestando grandes sumas de dinero para la industria y la construcción comercial y residencial. Cuando el efecto producto de las tensiones políticas y sociales disminuya, se espera que la actividad económica de este sector se reactive.
Hace dos días, María recibió una carta solicitando asesoría para la compra de dos viviendas por parte de una compañía internacional que desea ubicar a dos de sus empleados con sus familias en la ciudad. Las solicitudes incluyen las siguientes condiciones:
df <- vivienda
# Inspección inicial rápida
glimpse(df)
## 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…
miss_var_summary(df) # Ver cuántos datos faltan por variable
## # A tibble: 13 × 3
## variable n_miss pct_miss
## <chr> <int> <num>
## 1 piso 2638 31.7
## 2 parqueaderos 1605 19.3
## 3 id 3 0.0360
## 4 zona 3 0.0360
## 5 estrato 3 0.0360
## 6 areaconst 3 0.0360
## 7 banios 3 0.0360
## 8 habitaciones 3 0.0360
## 9 tipo 3 0.0360
## 10 barrio 3 0.0360
## 11 longitud 3 0.0360
## 12 latitud 3 0.0360
## 13 preciom 2 0.0240
gg_miss_var(df)
base_1 <- df %>%
filter(tipo == "Casa", zona == "Zona Norte")
#Mostrar los primeros 3 registros
head(base_1, 3)
## # A tibble: 3 × 13
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1209 Zona N… 02 5 320 150 2 4 6
## 2 1592 Zona N… 02 5 780 380 2 3 3
## 3 4057 Zona N… 02 6 750 445 NA 7 6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
Se realiza un filtro de la base de datos como se menciona en la descripción del ejercicio. En los resultados se puede evidenciar que la base de datos quedó filtrada por tipo “Casa” y “Zona Norte” de la ciudad, mostrando las 3 primeras observaciones.
-1.2. Tablas que comprueban la consulta
Se realiza una tabla con el fin de identificar que se realizó el filtro correctamente. Luego, se realiza una visualización del mapa con los puntos bases para determinar si en realidad pertenecen a la zona norte.
tabla_sin_frecuencia <- base_1 %>%
select(zona, estrato, tipo, barrio, piso, preciom, areaconst, parqueaderos, banios, habitaciones, longitud, latitud) %>%
distinct()
datatable(
tabla_sin_frecuencia,
options = list(
pageLength = 5,
autoWidth = TRUE,
scrollX = TRUE,
lengthMenu = c(5, 10, 20, 50),
dom = 'Bfrtip',
columnDefs = list(list(className = 'dt-center', targets = "_all")) # 🔹 Centrar todo
),
class = "cell-border stripe hover",
caption = htmltools::tags$caption(
style = 'caption-side: top; text-align: center;
color: black; font-size: 18px; font-weight: bold;',
"Base de Datos"
)
) %>%
formatStyle(
names(tabla_sin_frecuencia),
color = 'black'
) %>%
formatStyle(
0,
backgroundColor = 'skyblue',
color = 'white',
fontWeight = 'bold'
)
# Filtrar registros con coordenadas
base_map <- base_1 %>%
filter(!is.na(longitud), !is.na(latitud))
# Paleta de colores por zona
zonas <- unique(base_map$zona)
palette <- colorFactor(palette = "Set1", domain = zonas)
# Mapa interactivo
leaflet(base_map) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
radius = 5,
color = ~palette(zona),
stroke = FALSE,
fillOpacity = 0.8,
label = ~paste0(
"Zona: ", zona, "<br>",
"Barrio: ", barrio, "<br>",
"Tipo: ", tipo, "<br>",
"Latitud: ", latitud, "<br>",
"Longitud: ", longitud
)
) %>%
addLegend(
"bottomright",
pal = palette,
values = ~zona,
title = "Zona",
opacity = 1
)
Al analizar la visualización, se observa que aunque la mayor densidad de registros se concentra efectivamente en la zona norte de Cali, existe una dispersión significativa de puntos hacia el centro y el sur de la ciudad. Esta discrepancia entre la etiqueta de la leyenda (“Zona Norte”) y la ubicación real de los marcadores sugiere una inconsistencia en la categorización original de los datos. El hallazgo evidencia que los puntos han sido asignados administrativamente a una zona sin una validación geográfica previa, lo que subraya la necesidad técnica de emplear polígonos oficiales de división territorial para garantizar la precisión espacial en el análisis.
En cuanto a la gestión de estos errores, la corrección de los registros ubicados fuera de la zona no se ha realizado debido a las limitaciones actuales del proceso de formación. Al no haberse abordado aún las técnicas avanzadas de georreferenciación y validación espacial en el desarrollo del curso, el análisis se mantiene fiel a la fuente primaria para evitar manipulaciones subjetivas. Esta decisión metodológica permite identificar las fallas de origen en la base de datos antes de proceder con herramientas de limpieza más complejas que serán integradas en etapas posteriores.
Finalmente, aunque se planteó como alternativa la verificación manual mediante el control de latitud y longitud, esta opción fue descartada por su baja fiabilidad en esta etapa. Sin herramientas de validación automatizada o bases de referencia cartográfica oficiales, el riesgo de introducir nuevos errores manuales es elevado. Por lo tanto, se concluye que mantener la distribución actual es la postura más rigurosa desde el punto de vista del aprendizaje, ya que permite documentar la importancia del diagnóstico de calidad de datos antes de cualquier toma de decisiones basada en mapas.
# 1. Preparación de datos (Numéricos y sin NAs)
df_num <- na.omit(df[, c("preciom", "areaconst", "banios", "habitaciones")])
cor_matrix <- round(cor(df_num), 2) # Redondeamos a 2 decimales para que quepa bien
cor_melted <- melt(cor_matrix)
# 2. Creación del Mapa de Calor con anotaciones
plot_ly(x = cor_melted$Var1,
y = cor_melted$Var2,
z = cor_melted$value,
type = "heatmap",
colorscale = "RdBu",
zmin = -1, zmax = 1) %>%
add_annotations(x = cor_melted$Var1,
y = cor_melted$Var2,
text = cor_melted$value, # Aquí imprimimos el valor de z
showarrow = FALSE,
font = list(color = "black", size = 12)) %>%
layout(title = "<b>Matriz de Correlación: Peso de las Variables</b>",
xaxis = list(title = ""),
yaxis = list(title = ""))
La matriz de correlación revela que el área construida (0.69) es el factor con mayor peso sobre el precio de la vivienda, seguido muy de cerca por el número de baños (0.67). Lo que confirma que el valor de un inmueble en este mercado depende más de su amplitud que de la cantidad de dormitorios. Es notable que las habitaciones presentan la correlación más débil con el precio (0.26), sugiriendo que el mercado no valora simplemente el número de estancias, sino la calidad y el espacio funcional (baños y metros totales). Además, la alta correlación entre el área y los baños (0.65) indica una relación de proporcionalidad física
# 1. Limpieza de datos (Quitamos NAs en las variables clave)
df_clean <- df %>%
filter(!is.na(estrato), !is.na(preciom), !is.na(areaconst))
# 2. Creación del gráfico interactivo
fig <- plot_ly(data = df_clean,
x = ~areaconst,
y = ~preciom,
color = ~as.factor(estrato), # Color por estrato
type = "scatter",
mode = "markers",
# Personalizamos el texto que aparece al pasar el mouse (Tooltip)
text = ~paste("<b>Zona:</b>", zona,
"<br>Precio: $", preciom, "M",
"<br>Área:", areaconst, "m²",
"<br>Estrato:", estrato,
"<br>Habitaciones:", habitaciones,
"<br>Baños:", banios),
hoverinfo = "text") %>%
layout(
title = list(text = "<b>Análisis de Correlación: Precio vs Área</b><br><sup>Segmentado por Estrato y Zona</sup>"),
xaxis = list(title = "Área Construida (m²)"),
yaxis = list(title = "Precio (Millones COP)"),
legend = list(title = list(text = "<b>Estrato</b>")),
margin = list(t = 80) # Espacio para el subtítulo
)
fig
Existe una correlación positiva entre el área construida y el precio. Es decir, a medida que aumenta la superficie de la vivienda, el precio tiende a subir. Sin embargo, esta relación no es lineal para todos los casos; se observa una gran dispersión (variabilidad) a medida que el área aumenta.
Estrato 6 (Rosa): Es el que presenta la pendiente más inclinada. Esto indica que el valor del metro cuadrado es significativamente más alto que en los demás estratos. Puedes tener una casa de 250 m² en estrato 6 que cuesta el doble que una de la misma área en estrato 4.
Estratos 3 y 4 (Verde y Naranja): Se concentran en la base de la gráfica. Su crecimiento es más horizontal: el área puede aumentar considerablemente (llegando hasta los 1500 m² o más en el estrato 3), pero el precio se mantiene relativamente bajo en comparación con los estratos altos.
-La mayor concentración de datos se encuentra en viviendas de menos de 500 m² y precios por debajo de los 1.000 millones.
-El mercado de “lujo” o niveles altos (Estratos 5 y 6) muestra mucha más variabilidad. Esto sugiere que en estos estratos influyen más otras variables que configuraste en el plotly (como la zona, el número de baños o acabados de lujo) que el área por sí sola.
# Limpieza rápida para el Boxplot
df_box <- df[!is.na(df$estrato) & !is.na(df$preciom), ]
fig2 <- plot_ly(df_box, x = ~as.factor(estrato), y = ~preciom,
type = "box",
color = ~as.factor(estrato),
boxpoints = "outliers") %>% # Muestra puntos que se salen del rango normal
layout(title = "Distribución del Precio por Estrato",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio (Millones COP)"),
showlegend = FALSE)
fig2
El análisis de correlación revela una relación positiva y directa entre el área construida y el precio de la vivienda, aunque esta conexión está fuertemente mediada por el estrato socioeconómico. Mientras que en los estratos 3 y 4 los precios se mantienen en una franja baja y estable a pesar del aumento del metraje, en los estratos 5 y 6 la pendiente de crecimiento es mucho más pronunciada. Esto indica que el valor del metro cuadrado no es una constante en la ciudad, sino que se multiplica exponencialmente al subir de estrato, donde factores como la exclusividad y la ubicación tienen un peso mayor que el tamaño físico de la propiedad.
El gráfico de cajas (boxplot) confirma una segmentación de mercado marcada, especialmente en el estrato 6, que presenta la mediana más alta y la mayor dispersión de precios. A diferencia de los estratos bajos, donde los precios están más agrupados y son predecibles, el estrato 6 muestra una caja mucho más amplia, lo que refleja una gran heterogeneidad en la oferta. Esta variabilidad sugiere que, en niveles altos, el precio final depende de variables de lujo adicionales —como el número de baños o acabados específicos— que generan una brecha significativa incluso entre viviendas con características básicas similares.
Finalmente, la presencia de numerosos valores atípicos (outliers) en todos los estratos indica la existencia de propiedades excepcionales que rompen la norma de su entorno. Es notable ver viviendas en estratos 3 y 4 que alcanzan precios de estratos superiores, lo cual suele asociarse a un uso del suelo comercial o áreas construidas masivas que compensan la ubicación. En conclusión, para un modelo predictivo preciso, el área por sí sola es insuficiente; se requiere un análisis de interacción entre el estrato y las comodidades internas (baños y habitaciones) para capturar la verdadera dinámica de valor observada en los datos.
# Limpieza de NAs en las variables a comparar
df_banos <- df %>% filter(!is.na(banios), !is.na(preciom))
fig_banos <- plot_ly(df_banos,
x = ~as.factor(banios),
y = ~preciom,
type = "box",
color = ~as.factor(banios),
colors = viridis(10)) %>% # genera lista de 10 colores
layout(title = "<b>Impacto del Número de Baños en el Precio</b>",
xaxis = list(title = "Número de Baños"),
yaxis = list(title = "Precio (Millones COP)"),
showlegend = FALSE)
fig_banos
El gráfico confirma una clara tendencia ascendente en el precio de la vivienda a medida que aumenta el número de baños, reafirmando su rol como una variable de valorización crítica en este mercado. Se observa que el salto de precio más significativo ocurre entre las viviendas de 2 y 5 baños, donde no solo sube la mediana, sino que la dispersión de precios (el tamaño de las cajas) se amplía drásticamente, sugiriendo que a partir de los 4 baños entramos en un segmento de propiedades de alta gama o con áreas construidas muy extensas. Es llamativo el alto número de valores atípicos (puntos superiores) en las categorías de 2 a 5 baños, lo que indica que existen inmuebles con pocos baños pero precios muy elevados, probablemente debido a una ubicación privilegiada en estrato 6.
Finalmente, a partir de los 8 baños la muestra parece ser menor y más inestable, pero el nivel base de precios se mantiene significativamente alto, consolidando la idea de que la infraestructura sanitaria es un indicador directo del lujo y la funcionalidad de la propiedad.
# Limpieza de NAs para habitaciones y precio
df_hab <- df %>% filter(!is.na(habitaciones), !is.na(preciom))
fig_hab <- plot_ly(df_hab,
x = ~as.factor(habitaciones),
y = ~preciom,
type = "box",
color = ~as.factor(habitaciones),
colors = viridis(10)) %>%
layout(title = "<b>Relación: Número de Habitaciones vs Precio</b>",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio (Millones COP)"),
showlegend = FALSE)
fig_hab
A diferencia de los baños, el número de habitaciones no muestra una relación lineal clara con el precio, lo que confirma que el mercado inmobiliario actual no castiga necesariamente a las viviendas con pocas alcobas si estas ofrecen mayor exclusividad. Se observa que el pico de valorización máxima (los puntos más altos cerca de los 2.000 millones) se concentra en propiedades de 3 a 5 habitaciones, mientras que las casas con 6 o más alcobas tienden a estabilizar o incluso reducir sus medianas de precio. Esto sugiere que el segmento de lujo prefiere espacios amplios y bien distribuidos sobre una alta densidad de habitaciones, la cual podría estar más asociada a viviendas de tipo multifamiliar o con una estructura más antigua y menos valorizada por metro cuadrado.
# 1. Limpieza y preparación (Quitamos NAs en zona)
df_zona <- df %>% filter(!is.na(zona), !is.na(preciom))
# 2. Gráfico de cajas por zona
fig_zona <- plot_ly(df_zona,
x = ~zona,
y = ~preciom,
type = "box",
color = ~zona,
colors = "Set2") %>%
layout(title = "<b>Distribución de Precios por Zona Geográfica</b>",
xaxis = list(title = "Zona"),
yaxis = list(title = "Precio (Millones COP)"),
showlegend = FALSE)
fig_zona
El análisis por zonas geográficas revela una marcada jerarquía de precios, donde la Zona Oeste destaca como el mercado más exclusivo al presentar la mediana de precios más alta y la mayor variabilidad en sus valores. Por otro lado, la Zona Sur y la Zona Norte, aunque tienen medianas más moderadas, muestran una cantidad excepcional de valores atípicos (outliers) que superan los 1.500 millones, lo que indica la presencia de focos de muy alta valorización dentro de sectores mayoritariamente de clase media. Finalmente, la Zona Oriente se consolida como el sector más asequible y homogéneo, con los precios más bajos y la menor dispersión del mercado, contrastando drásticamente con el dinamismo y los techos de precio observados en el occidente de la ciudad.
# 1. Preparación de los datos: Convertir estrato a factor para una interpretación correcta
df_model <- df %>%
mutate(estrato = as.factor(estrato),
zona = as.factor(zona)) %>%
filter(!is.na(preciom), !is.na(areaconst), !is.na(estrato),
!is.na(habitaciones), !is.na(parqueaderos), !is.na(banios))
# 2. Estimación del modelo de regresión lineal múltiple
modelo_multiple <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios,
data = df_model)
# 3. Ver resultados detallados
summary(modelo_multiple)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = df_model)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1448.96 -77.85 -9.38 48.99 1050.82
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -8.30775 9.47346 -0.877 0.381
## areaconst 0.83963 0.02132 39.380 < 2e-16 ***
## estrato4 33.16217 7.99305 4.149 3.38e-05 ***
## estrato5 79.49619 7.79744 10.195 < 2e-16 ***
## estrato6 295.71665 9.14625 32.332 < 2e-16 ***
## habitaciones -28.23331 2.19273 -12.876 < 2e-16 ***
## parqueaderos 67.64386 2.50357 27.019 < 2e-16 ***
## banios 56.09964 2.54020 22.085 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 170 on 6709 degrees of freedom
## Multiple R-squared: 0.7427, Adjusted R-squared: 0.7424
## F-statistic: 2766 on 7 and 6709 DF, p-value: < 2.2e-16
Área construida (0.84): Por cada \(m^2\) adicional, el precio aumenta en promedio 0.84 millones. Es un resultado totalmente lógico, siendo el motor físico del valor.
Estrato (Referencia Estrato 3): Los coeficientes de \(33.1\) (Estrato 4), \(79.5\) (Estrato 5) y \(295.7\) (Estrato 6) muestran que el simple hecho de cambiar de ubicación a un estrato superior incrementa el valor de forma drástica. Es coherente con la realidad socioeconómica, donde el estrato 6 actúa como un mercado premium.
Parqueaderos (67.6) y Baños (56.1): Ambos tienen un impacto positivo fuerte. Resulta lógico que un parqueadero aporte más que un baño, dada la escasez de espacio de estacionamiento en zonas urbanas densas.
Habitaciones (-28.2): El coeficiente negativo es contraintuitivo pero lógico en este contexto: si mantenemos el área fija, tener más habitaciones implica que cada una es más pequeña, lo cual resta valor frente a espacios amplios y abiertos.
El coeficiente de determinación \(R^2 = 0.7427\) indica que el modelo logra explicar el 74.27% de la variabilidad de los precios de las viviendas. Para un mercado tan complejo como el inmobiliario, este es un ajuste sólido, sugiriendo que las variables físicas y el estrato capturan la mayor parte de la lógica de precios. Sin embargo, existe un 25.73% de la variación (ruido) que el modelo aún no explica, representado por el Error Estándar Residual de 170 millones.
Aunque el modelo es bueno, el ajuste podría mejorar mediante:
Inclusión de la Zona: Como vimos en el análisis exploratorio, la zona geográfica tiene una variabilidad propia que no se reduce solo al estrato.
Modelado de Interacciones: El valor del metro cuadrado no es el mismo en estrato 3 que en estrato 6; incluir un término de interacción (areaconst * estrato) capturaría mejor esta realidad.
Tratamiento de valores extremos: Eliminar propiedades con precios atípicos (outliers) que sesgan la línea de regresión, permitiendo que el modelo se ajuste mejor a la “vivienda promedio”.
Este evalúa si los residuos se distribuyen siguiendo una campana de Gauss.
\(H_0\): \(\varepsilon_i \sim N(0, \sigma^2)\) (Los residuos siguen una distribución normal).
\(H_1\): \(\varepsilon_i\) no siguen una distribución normal.
# 1. Extracción de residuos y valores ajustados
residuos <- residuals(modelo_multiple)
ajustados <- fitted(modelo_multiple)
# --- a. Normalidad de los errores ---
par(mfrow = c(1, 2))
# Histograma con curva normal
hist(residuos, breaks = 50, freq = FALSE, col = "skyblue",
main = "Histograma de los residuos", xlab = "Residuos")
curve(dnorm(x, mean = mean(residuos), sd = sd(residuos)),
col = "gray", lwd = 2, add = TRUE)
# Gráfico Q-Q
qqnorm(residuos, main = "Grafico Q-Q de los residuos")
qqline(residuos, col = "gray", lwd = 2)
Los gráficos de diagnóstico confirman que el modelo no cumple con el supuesto de normalidad de los residuos, presentando una distribución con colas pesadas y una desviación significativa en los extremos del gráfico Q-Q. El histograma muestra una concentración excesiva de errores cerca del cero (leptocurtosis) y valores atípicos que se alejan drásticamente de la línea roja teórica, lo que sugiere que el modelo tiene dificultades para predecir con precisión las propiedades de precios extremos (muy bajos o muy altos).
Esta falta de normalidad invalida la precisión de los intervalos de confianza y las pruebas de significancia, por lo que se recomienda aplicar una transformación logarítmica a la variable precio o un tratamiento de valores atípicos para estabilizar la varianza y mejorar el ajuste estadístico.
# Test de Anderson-Darling
ad.test(residuos)
##
## Anderson-Darling normality test
##
## data: residuos
## A = 240.07, p-value < 2.2e-16
Los resultados de la prueba de Anderson-Darling confirman de manera formal lo observado en los gráficos Q-Q y el histograma: dado que el p-value es extremadamente pequeño (\(< 2.2e-16\)), se rechaza la hipótesis nula de normalidad. Esto significa que los residuos del modelo no siguen una distribución normal, lo cual es consecuencia directa de la alta variabilidad y los valores extremos presentes en los precios, especialmente en los estratos más altos. Aunque el modelo captura tendencias generales, este incumplimiento sugiere que las inferencias estadísticas (como los intervalos de confianza) podrían no ser del todo precisas, reforzando la necesidad de considerar transformaciones de variables o modelos robustos para mejorar la fiabilidad de las predicciones.
# --- b. Media de los errores E[e]=0 ---
par(mfrow = c(1, 1))
plot(residuos, type = "p", col = "yellow",
main = "Residuos vs Observaciones",
ylab = "Residuos", xlab = "Índice")
abline(h = 0, col = "blue", lwd = 2)
El conjunto de gráficas revela que el precio de la vivienda está fuertemente condicionado por la infraestructura sanitaria y la ubicación, más que por la cantidad de dormitorios. Mientras que el número de baños muestra una correlación positiva y constante con el valor del inmueble, el número de habitaciones presenta una relación estancada a partir de las cinco unidades, sugiriendo que el mercado valora más la amplitud y el estatus que la alta densidad habitacional. Geográficamente, la Zona Oeste se posiciona como el sector de mayor lujo y exclusividad, contrastando con la homogeneidad de la Zona Oriente.
Finalmente, el gráfico de residuos valida que el modelo está centrado en cero, lo que indica la ausencia de un sesgo sistemático; sin embargo, la presencia de puntos dispersos y alejados de la línea central evidencia heterocedasticidad y valores atípicos que dificultan la precisión del modelo en los segmentos de precios más altos, confirmando que factores no lineales influyen significativamente en la valorización final.
la gráfica de residuos vs. observaciones indica que, aunque el modelo está centrado, la alta dispersión y los valores atípicos reflejan una heterocedasticidad que limita la precisión en los segmentos de precios más elevados.
# Prueba t de Student para la media
t.test(residuos, mu = 0)
##
## One Sample t-test
##
## data: residuos
## t = 2.0543e-14, df = 6716, p-value = 1
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
## -4.065066 4.065066
## sample estimates:
## mean of x
## 4.259936e-14
El conjunto de hallazgos revela que el mercado inmobiliario prioriza la exclusividad geográfica y la infraestructura de servicios sobre la densidad habitacional. Mientras que el número de baños y la Zona Oeste muestran una relación directa y ascendente con el precio, el número de habitaciones presenta rendimientos decrecientes, sugiriendo que el lujo se asocia a espacios amplios y no a una mayor cantidad de recámaras. Respecto a la validez estadística, la prueba t para la media de los residuos (\(p\text{-value} = 1\)) confirma que no se rechaza la hipótesis nula (\(H_0: \mu = 0\)), demostrando que el modelo no tiene un sesgo sistemático.
# --- c. Varianza constante (Homocedasticidad) ---
plot(ajustados, residuos,
col = "skyblue", pch = 19,
main = "Residuos vs Valores Ajustados",
xlab = "Valores Ajustados", ylab = "Residuos")
abline(h = 0, col = "brown", lwd = 2)
Este gráfico de Residuos vs. Valores Ajustados es fundamental para
validar la homocedasticidad del modelo. Se observa claramente un patrón
de “embudo” o “trompeta”, donde la dispersión de los residuos aumenta a
medida que el valor predicho del precio es mayor; esto confirma la
presencia de heterocedasticidad, lo que significa que la varianza del
error no es constante y el modelo pierde precisión en las viviendas de
gama alta.
Asimismo, la presencia de puntos significativamente alejados de la línea roja central (el cero) evidencia valores atípicos que el modelo no logra explicar con las variables actuales.
# Test de Breusch-Pagan
bptest(modelo_multiple)
##
## studentized Breusch-Pagan test
##
## data: modelo_multiple
## BP = 1303.8, df = 7, p-value < 2.2e-16
El Test de Breusch-Pagan, con un p-valor ínfimo (\(< 2.2e-16\)), confirma estadísticamente la heterocedasticidad que ya se intuía en los gráficos de dispersión: la variabilidad de los precios no es constante, siendo mucho más errática en las propiedades de alto valor, como las ubicadas en la Zona Oeste o pertenecientes al Estrato 6.
Aunque variables como el área y los parqueaderos son predictores potentes y significativos, la presencia de este fenómeno implica que los errores estándar están sesgados, lo que resta confiabilidad a las pruebas de hipótesis y a las predicciones en los segmentos de lujo.
# --- d. Independencia de los errores ---
plot(residuos, type = "l",
main = "Residuos vs. Observaciones (Independencia)",
xlab = "Observaciones", ylab = "Residuos")
abline(h = 0, col = "brown")
Permite evaluar visualmente el supuesto de independencia de los errores.
Aunque los residuos parecen oscilar de forma aleatoria alrededor de la
línea cero, lo que sugiere la ausencia de un sesgo global, la presencia
de “picos” o clústeres de alta variabilidad en ciertos tramos de las
observaciones indica que existen factores no capturados por el modelo
que afectan a grupos específicos de datos.
En conclusión, mientras el modelo es insesgado en promedio, la interdependencia detectada sugiere que el orden o la agrupación de los datos (posiblemente por cercanía geográfica dentro de una misma zona) influye en el error, lo que recomienda el uso de modelos con efectos espaciales o errores estándar robustos para una inferencia más precisa.
# Test de Durbin-Watson
dwtest(modelo_multiple)
##
## Durbin-Watson test
##
## data: modelo_multiple
## DW = 1.7551, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
El Test de Durbin-Watson, con un valor de 1.755 y un p-valor ínfimo (\(< 2.2e-16\)), confirma la existencia de una autocorrelación positiva en los residuos; esto implica que el error de predicción en una vivienda tiende a parecerse al de sus vecinas, probablemente debido a dinámicas locales de barrio que el modelo no captura totalmente. Al integrar esto con el boxplot de zonas, se evidencia que mientras zonas como el Oriente son estables y predecibles, el Oeste introduce un ruido significativo al modelo por su alta variabilidad y precios excepcionales.
# Definir los datos de la Vivienda 1 (Escenario Estrato 4 y 5)
vivienda_1_est4 <- data.frame(
areaconst = 200,
parqueaderos = 1,
banios = 2,
habitaciones = 4,
estrato = "4",
zona = "Norte"
)
vivienda_1_est5 <- vivienda_1_est4
vivienda_1_est5$estrato <- "5"
# Realizar las predicciones
pred_est4 <- predict(modelo_multiple, newdata = vivienda_1_est4)
pred_est5 <- predict(modelo_multiple, newdata = vivienda_1_est5)
# Resultados
cat("Precio estimado (Estrato 4):", round(pred_est4, 2), "millones\n")
## Precio estimado (Estrato 4): 259.69 millones
cat("Precio estimado (Estrato 5):", round(pred_est5, 2), "millones")
## Precio estimado (Estrato 5): 306.02 millones
El precio estimado es de 259.69 millones.Escenario Estrato 5:
El precio estimado es de 306.02 millones.
En ambos escenarios (estrato 4 y 5), el valor estimado por el modelo es inferior al presupuesto del cliente de 350 millones
# Filtrar ofertas potenciales para la Vivienda 1
ofertas_v1 <- df %>%
filter(
zona == "Zona Norte",
areaconst >= 180 & areaconst <= 220, # Rango cercano a 200m2
preciom <= 350, # Límite del crédito
estrato %in% c("4", "5") # Estratos solicitados
) %>%
head(5) # Seleccionar las primeras 5 para la discusión
# Ver las ofertas seleccionadas
print(ofertas_v1[, c("preciom", "areaconst", "estrato", "habitaciones", "latitud", "longitud")])
## # A tibble: 5 × 6
## preciom areaconst estrato habitaciones latitud longitud
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 275 190 4 3 3.45 -76.5
## 2 280 180 4 3 3.39 -76.5
## 3 340 200 4 3 3.40 -76.6
## 4 350 200 5 4 3.49 -76.5
## 5 335 202 5 5 3.48 -76.5
leaflet(ofertas_v1) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Precio: $", preciom, "M<br>",
"Área:", areaconst, "m2<br>",
"Estrato:", estrato)
) %>%
addCircles(lng = -76.5, lat = 3.45, radius = 2000, color = "red", fill = FALSE) # Referencia Zona Norte
Para dar respuesta a la solicitud de la Vivienda 1, se realizó un filtrado estratégico en la base de datos de la zona Norte, seleccionando propiedades con un área cercana a los 200 \(m^2\) y estratos 4 o 5, cuyo valor no excediera el crédito preaprobado de 350 millones de pesos. El análisis espacial representado en el mapa revela cinco ofertas ideales con precios que oscilan entre los 275 y 350 millones, lo cual es plenamente consistente con las predicciones del modelo (259.69 - 306.02 millones) y confirma la viabilidad financiera del proyecto.
Estas opciones no solo cumplen con los requisitos de 4 habitaciones y al menos 2 baños, sino que se distribuyen en puntos estratégicos del sector norte de Cali, ofreciendo al cliente un margen de ahorro o inversión adicional, dado que ninguna oferta supera su capacidad de endeudamiento y la mayoría se sitúa significativamente por debajo del límite máximo.
# Definir datos Vivienda 2
vivienda_2_est5 <- data.frame(
areaconst = 300, parqueaderos = 3, banios = 3,
habitaciones = 5, estrato = "5", zona = "Sur"
)
vivienda_2_est6 <- vivienda_2_est5
vivienda_2_est6$estrato <- "6"
# Predicciones
pred2_est5 <- predict(modelo_multiple, newdata = vivienda_2_est5)
pred2_est6 <- predict(modelo_multiple, newdata = vivienda_2_est6)
# Resultados
cat("Precio estimado (Estrato 4):", round(pred2_est5, 2), "millones\n")
## Precio estimado (Estrato 4): 553.14 millones
cat("Precio estimado (Estrato 5):", round(pred2_est6, 2), "millones")
## Precio estimado (Estrato 5): 769.36 millones
El análisis integral de la segunda solicitud (vivienda de 300 \(m^2\) en la Zona Sur) confirma que el proyecto es financieramente viable, con precios estimados de 553.14 millones para estrato 5 y 769.36 millones para estrato 6, valores que se mantienen por debajo del crédito preaprobado de 850 millones.
No obstante, la validez estadística de estas predicciones es limitada debido al incumplimiento de supuestos críticos: el Test de Breusch-Pagan (\(p < 2.2e-16\)) y el gráfico de residuos contra valores ajustados evidencian una marcada heterocedasticidad, indicando que el modelo pierde precisión y aumenta su variabilidad en este segmento de precios altos.
Asimismo, el Test de Durbin-Watson (1.7551) revela una autocorrelación positiva, lo que sugiere que factores espaciales no incluidos están afectando sistemáticamente las estimaciones. En conclusión, aunque el presupuesto del cliente es suficiente, las decisiones deben tomarse con cautela dado que el modelo tiende a ser menos confiable y presenta mayor dispersión de error al evaluar propiedades de lujo en la Zona Sur.