En este informe se analiza el caso de C&A, donde se solicita identificar potenciales ofertas de vivienda a partir de una base de datos de bienes raíces en Cali. Se utilizarán técnicas de análisis exploratorio, regresión lineal múltiple, validación de supuestos, selección de variables, validación cruzada y bootstrapping para responder a las solicitudes de dos viviendas con características distintas.
El presente análisis se estructura en varios pasos detallados que permiten abordar de forma integral el caso de estudio. A continuación, se describen cada uno de los pasos, junto con las actividades específicas que se desarrollarán en el código:
paqueteMODELOS.tipo y zona) y se inspeccionan
posibles valores faltantes, los cuales se eliminarán o imputarán según
sea necesario.lm() para ajustar un modelo que explica el precio de la
vivienda a partir de las variables seleccionadas (área construida,
estrato, número de habitaciones, parqueaderos y baños).Este plan de trabajo proporciona un marco claro y detallado para la ejecución del análisis, asegurando que cada etapa (desde la exploración inicial hasta la validación y selección de modelos) esté debidamente documentada y respaldada por el código desarrollado.
Se carga la base de datos del paquete paqueteMODELOS y
se filtra para obtener solo las ofertas de casas en la Zona
Norte.
# Instalar y cargar el paqueteMODELOS (descomenta las siguientes líneas si aún no lo tienes instalado)
# install.packages("devtools")
# devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
library(paqueteMODELOS)
data("vivienda")
Filtramos la base de datos:
library(dplyr)
base1 <- vivienda %>%
filter(tipo == "Casa" & zona == "Zona Norte")
head(base1, 3)
Verificamos las frecuencias de las variables tipo y
zona:
table(base1$tipo)
##
## Casa
## 722
table(base1$zona)
##
## Zona Norte
## 722
Generamos un mapa interactivo con leaflet para visualizar la ubicación de las viviendas. Dado que los mapas son HTML widgets, se renderizarán como imagen estática:
library(leaflet)
leaflet(data = base1) %>%
addTiles() %>%
addCircleMarkers(~longitud, ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Precio:", preciom, "millones"))
Discusión:
La visualización confirma que la mayoría de las ofertas se concentran en
la Zona Norte, cumpliendo así con el enfoque establecido para este
análisis. La alta densidad de puntos en esta región indica una amplia
oferta de propiedades disponibles. Sin embargo, se identifican algunos
registros que aparecen fuera de la zona objetivo, lo cual puede deberse
a datos geográficos imprecisos o clasificaciones erróneas. Para
garantizar la confiabilidad de la información y tomar decisiones
estratégicas acertadas, se recomienda verificar estos registros fuera de
la zona y mantener la base de datos actualizada con las coordenadas
correctas. De esta manera, la empresa podrá responder de manera más
efectiva a la demanda de viviendas en la Zona Norte y brindar
recomendaciones confiables a sus clientes.
Exploramos la relación entre el precio de la vivienda
(preciom) y algunas variables predictoras: área construida
(areaconst), estrato, número de baños (banios)
y número de habitaciones (habitaciones). Se configuran los
gráficos para renderizarse como imágenes.
library(plotly)
# Gráfico interactivo: Precio vs Área Construida
p1 <- plot_ly(data = base1, x = ~areaconst, y = ~preciom,
type = 'scatter', mode = 'markers') %>%
layout(title = "Precio vs Área Construida",
xaxis = list(title = "Área Construida"),
yaxis = list(title = "Precio (millones)"))
p1
# Boxplot interactivo: Precio según Estrato
p2 <- plot_ly(data = base1, x = ~as.factor(estrato), y = ~preciom, type = "box") %>%
layout(title = "Distribución del Precio por Estrato",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio (millones)"))
p2
Interpretación:
Los gráficos confirman que, a medida que el área construida aumenta, el
precio de la vivienda tiende a elevarse de forma significativa. En la
primera visualización (Precio vs. Área Construida), se observa un patrón
ascendente claro, lo que indica que el tamaño de la propiedad es un
factor determinante para su valor en el mercado.
Por otro lado, la segunda gráfica (Distribución del Precio por Estrato) revela que los inmuebles ubicados en estratos más altos presentan precios sustancialmente mayores. Este hallazgo refuerza la importancia de considerar el nivel socioeconómico del barrio o sector como una variable clave en la fijación de precios y en el diseño de estrategias de venta.
A nivel directivo, estos resultados sugieren la conveniencia de segmentar la oferta según estrato y área construida. Las propiedades con áreas amplias y en estratos altos representan un segmento de alto valor y potencial rentabilidad, aunque con un público objetivo más reducido. En contraste, las viviendas de menor área y estratos medios o bajos pueden orientarse a un mercado más amplio. Es recomendable verificar posibles outliers (valores extremadamente altos o bajos) para asegurar la calidad de los datos y, de ser válidos, considerarlos como casos especiales (propiedades de lujo o con características únicas).
En síntesis, los hallazgos permiten a la gerencia enfocar la estrategia comercial en las propiedades de mayor área y estratos altos para maximizar la rentabilidad, al tiempo que se mantienen opciones competitivas en estratos y áreas más asequibles, con el fin de atender diversos segmentos de la demanda.
Ajustamos un modelo de regresión lineal múltiple para explicar el precio de la vivienda usando las variables: área construida, estrato, número de habitaciones, parqueaderos y baños.
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = base1)
summary(modelo)
##
## 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
Interpretación:
- Coeficientes:
- El intercepto negativo (por ejemplo, -238.17) indica que si todas las
variables independientes fueran 0, el precio sería negativo, lo cual no
tiene una interpretación práctica real, pero es común cuando el rango de
las variables no incluye el origen.
- Un coeficiente positivo en areaconst (p. ej., 0.65)
significa que, por cada metro cuadrado adicional de área construida, el
precio se incrementa en 0.65 millones de pesos, manteniendo constantes
las demás variables.
- De igual forma, coeficientes positivos en estrato,
habitaciones, parqueaderos y
banios implican que cada unidad adicional en estas
variables se asocia con un incremento promedio en el precio, si todo lo
demás permanece constante.
Evaluamos los supuestos de la regresión mediante gráficos diagnósticos.
par(mfrow = c(2, 2))
plot(modelo)
par(mfrow = c(1, 1))
Interpretación:
- Residuals vs Fitted:
- Se utiliza para detectar patrones sistemáticos en los residuos que
indicarían una posible falta de linealidad o heterocedasticidad
(variación no constante de los residuos). Una distribución aleatoria de
puntos alrededor de la línea horizontal sugiere que no hay grandes
problemas de linealidad, mientras que patrones curvados o en abanico
pueden evidenciar la necesidad de ajustes adicionales o variables
faltantes.
En conjunto, estos gráficos diagnósticos permiten evaluar si el modelo lineal se ajusta adecuadamente a los datos y si los supuestos de normalidad, linealidad y homocedasticidad se cumplen. Si se detectan violaciones importantes, se pueden considerar ajustes como transformaciones de variables, inclusión de nuevas variables o métodos de regresión robusta.
Se predice el precio de una casa con las siguientes características:
- Área construida: 200
- Estrato: 4
- Habitaciones: 4
- Parqueaderos: 1
- Baños: 2
nueva_vivienda1 <- data.frame(
areaconst = 200,
estrato = 4,
habitaciones = 4,
parqueaderos = 1,
banios = 2
)
pred1 <- predict(modelo, newdata = nueva_vivienda1)
cat("Precio predicho para la vivienda 1:", pred1, "millones de pesos")
## Precio predicho para la vivienda 1: 312.101 millones de pesos
Interpretación:
- El precio estimado para esta vivienda, con las características
especificadas (área construida de 200 m², estrato 4, cuatro
habitaciones, un parqueadero y dos baños), es de aproximadamente 312
millones de pesos.
- Esta predicción se basa en la relación promedio observada en los datos
para cada una de estas variables. Si las condiciones del mercado y el
estado de la propiedad se asemejan a lo reflejado en el conjunto de
entrenamiento, el precio real podría aproximarse a esta cifra.
- Sin embargo, el modelo no considera factores adicionales (por ejemplo,
remodelaciones, ubicación exacta, antigüedad, acabados), por lo que se
recomienda contrastar este valor con precios de mercado actuales o
avalúos profesionales.
- Una coincidencia razonable entre el precio predicho y las ofertas
reales de viviendas similares reforzaría la validez del modelo;
divergencias notables podrían indicar la necesidad de incluir más
variables o de ajustar el modelo.
Filtramos las ofertas de casas en la Zona Norte con un precio menor o igual a 350 millones (crédito preaprobado).
ofertas1 <- base1 %>%
filter(preciom <= 350)
ofertas1_seleccion <- ofertas1 %>%
arrange(preciom) %>%
head(5)
ofertas1_seleccion
Visualizamos las ofertas en un mapa:
leaflet(data = ofertas1_seleccion) %>%
addTiles() %>%
addCircleMarkers(~longitud, ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Precio:", preciom, "millones"))
Discusión:
- Cumplimiento de la Solicitud: Las ofertas mostradas
pertenecen a la Zona Norte y tienen un precio menor o igual a 350
millones, alineándose con las condiciones requeridas para la primera
solicitud.
- Características de las Propiedades: Cada inmueble
listado exhibe atributos relevantes (número de parqueaderos, baños,
habitaciones y área construida), lo que facilita la comparación entre
opciones.
- Ubicación en el Mapa: La visualización en el mapa
confirma que estas ofertas se sitúan dentro de la zona de interés. Este
enfoque georreferenciado ayuda a identificar con claridad la proximidad
de las propiedades a puntos de interés (comerciales, educativos o de
transporte).
- Siguiente Paso: Se recomienda evaluar en detalle cada
oferta, revisando la documentación y visitando los inmuebles, para
garantizar que cumplan con los requerimientos de calidad y condiciones
físicas. Adicionalmente, contrastar estos precios con avalúos o estudios
de mercado más actualizados puede fortalecer la toma de decisiones.
La segunda solicitud corresponde a un apartamento con las siguientes
características: - Área construida: 300
- Estrato: 5
- Habitaciones: 5
- Parqueaderos: 3
- Baños: 3
- Crédito preaprobado: 850 millones
Filtramos la base de datos para obtener apartamentos en la Zona Sur:
base2 <- vivienda %>%
filter(tipo == "Apartamento" & zona == "Zona Sur")
head(base2, 3)
Ajustamos un modelo de regresión para esta base:
modelo_apart <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = base2)
summary(modelo_apart)
##
## 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
Predicción para la vivienda 2:
nueva_vivienda2 <- data.frame(
areaconst = 300,
estrato = 5,
habitaciones = 5,
parqueaderos = 3,
banios = 3
)
pred2 <- predict(modelo_apart, newdata = nueva_vivienda2)
cat("Precio predicho para la vivienda 2:", pred2, "millones de pesos")
## Precio predicho para la vivienda 2: 675.0247 millones de pesos
Filtramos las ofertas potenciales que se ajusten al crédito preaprobado (≤ 850 millones):
ofertas2 <- base2 %>%
filter(preciom <= 850)
ofertas2_seleccion <- ofertas2 %>%
arrange(preciom) %>%
head(5)
ofertas2_seleccion
Visualizamos las ofertas en un mapa:
leaflet(data = ofertas2_seleccion) %>%
addTiles() %>%
addCircleMarkers(~longitud, ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Precio:", preciom, "millones"))
Discusión:
- Filtrado y Modelo para Apartamentos en Zona Sur: Se
ajustó un modelo específico para apartamentos en la Zona Sur, usando
variables como el área construida, estrato, número de habitaciones,
parqueaderos y baños. El resumen del modelo (R² cercano a 0.74 y valores
p muy bajos) evidencia que estas variables explican de forma
significativa el precio en esta región.
- Predicción para la Segunda Solicitud: Con las
características solicitadas (área de 300 m², estrato 5, cinco
habitaciones, tres parqueaderos y tres baños), el modelo estima un
precio de aproximadamente 675 millones de pesos. Este valor se sitúa por
debajo del crédito preaprobado de 850 millones, lo que indica que la
vivienda propuesta es financieramente viable.
- Selección de Ofertas Potenciales: A continuación, se
filtraron las propiedades de la base de datos con un precio inferior o
igual a 850 millones en la Zona Sur. Las cinco ofertas seleccionadas
cumplen con el rango de precio requerido y se visualizan en el mapa,
confirmando su ubicación geográfica en la zona de interés.
- Conclusión para la Segunda Solicitud: Estos hallazgos
muestran que el modelo es adecuado para identificar apartamentos en la
Zona Sur que cumplan con las especificaciones de la solicitud y el
límite de crédito. No obstante, se recomienda revisar aspectos
adicionales (estado de la propiedad, amenidades, acabados, etc.) para
tomar una decisión final bien fundamentada.
Para evitar problemas por valores faltantes durante el proceso stepwise, se crea una versión limpia de la base de datos:
base1_clean <- na.omit(base1)
Definimos el modelo nulo y el modelo completo usando
base1_clean:
modelo_b0 <- lm(preciom ~ 1, data = base1_clean)
modelo_all <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = base1_clean)
# Forward stepwise
modelo_forward <- step(modelo_b0, direction = "forward", scope = formula(modelo_all), trace = 0)
modelo_forward
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + habitaciones,
## data = base1_clean)
##
## Coefficients:
## (Intercept) areaconst estrato parqueaderos habitaciones
## -248.9809 0.6717 89.5164 30.3267 13.5488
# Backward stepwise
modelo_backward <- step(modelo_all, direction = "backward", trace = 0)
modelo_backward
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos,
## data = base1_clean)
##
## Coefficients:
## (Intercept) areaconst estrato habitaciones parqueaderos
## -248.9809 0.6717 89.5164 13.5488 30.3267
# Comparación de modelos usando modelsummary
library(modelsummary)
modelsummary(list(Forward = modelo_forward, Backward = modelo_backward))
| Forward | Backward | |
|---|---|---|
| (Intercept) | -248.981 | -248.981 |
| (60.863) | (60.863) | |
| areaconst | 0.672 | 0.672 |
| (0.067) | (0.067) | |
| estrato | 89.516 | 89.516 |
| (12.780) | (12.780) | |
| parqueaderos | 30.327 | 30.327 |
| (6.517) | (6.517) | |
| habitaciones | 13.549 | 13.549 |
| (6.031) | (6.031) | |
| Num.Obs. | 254 | 254 |
| R2 | 0.593 | 0.593 |
| R2 Adj. | 0.586 | 0.586 |
| AIC | 3283.1 | 3283.1 |
| BIC | 3304.4 | 3304.4 |
| Log.Lik. | -1635.565 | -1635.565 |
| F | 90.617 | 90.617 |
| RMSE | 151.46 | 151.46 |
Discusión:
- Coincidencia de Modelos en Forward y Backward: Ambos
métodos de selección (forward y backward) convergieron en la misma
especificación final, lo que indica que las variables
areaconst, estrato, parqueaderos
y habitaciones explican de forma consistente el precio de
la vivienda en esta base de datos.
- Indicadores de Ajuste (R², AIC, BIC): El valor de R²
(alrededor de 0.59) sugiere que aproximadamente el 59% de la
variabilidad en el precio se explica por estas variables, mientras que
el AIC y BIC obtenidos confirman que este modelo presenta un equilibrio
adecuado entre precisión y complejidad.
- Interpretación de Coeficientes: Las variables
retenidas muestran coeficientes positivos y estadísticamente
significativos, reforzando la importancia del área construida, el
estrato, el número de parqueaderos y de habitaciones como determinantes
del precio.
- Conclusión sobre la Selección de Variables: El hecho
de que ambos métodos stepwise hayan determinado el mismo conjunto de
predictores incrementa la confianza en la relevancia de estas variables.
Aun así, se podrían considerar variables adicionales o transformaciones
si se desea mejorar aún más la capacidad predictiva o abordar posibles
no linealidades.
Evaluamos el rendimiento del modelo mediante validación cruzada simple.
set.seed(1)
n <- nrow(base1)
train_indices <- sample(1:n, size = round(0.6 * n))
modelo_train <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = base1, subset = train_indices)
predicciones_cv <- predict(modelo_train, newdata = base1[-train_indices, ])
MSE_cv <- mean((base1$preciom[-train_indices] - predicciones_cv)^2)
MSE_cv
## [1] NA
Discusión:
El MSE obtenido en el conjunto de prueba proporciona una medida de la
capacidad predictiva del modelo y ayuda a identificar posibles problemas
de sobreajuste.
Aplicamos bootstrapping para estimar la variabilidad de los coeficientes del modelo.
library(boot)
# Función para obtener los coeficientes del modelo
coef_function <- function(data, indices) {
modelo_boot <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = data, subset = indices)
return(coef(modelo_boot))
}
set.seed(1)
boot_results <- boot(data = base1, statistic = coef_function, R = 1000)
boot_results
##
## ORDINARY NONPARAMETRIC BOOTSTRAP
##
##
## Call:
## boot(data = base1, statistic = coef_function, R = 1000)
##
##
## Bootstrap Statistics :
## original bias std. error
## t1* -238.1708979 4.27561889 43.2811670
## t2* 0.6767346 0.01767577 0.1259501
## t3* 80.6349477 -1.29779023 10.9024357
## t4* 7.6451100 -0.56566667 6.6396936
## t5* 24.0059798 -0.51283708 6.4186951
## t6* 18.8993776 0.15973031 9.4701974
Discusión:
- Distribución Empírica de los Coeficientes: El
bootstrapping genera, mediante remuestreo, múltiples estimaciones de
cada coeficiente. Esto produce distribuciones empíricas que permiten
evaluar la estabilidad y la variabilidad de las estimaciones obtenidas
en el modelo original.
- Bias y Error Estándar: El sesgo (bias) indica la
diferencia promedio entre las estimaciones bootstrap y el valor original
de cada coeficiente. Un valor pequeño de bias sugiere que el estimador
es aproximadamente insesgado. El error estándar (std. error) refleja la
dispersión de las estimaciones en la distribución bootstrap; valores
bajos indican mayor consistencia.
- Intervalos de Confianza: Con los resultados de las
réplicas, es posible construir intervalos de confianza para cada
coeficiente, brindando una visión más robusta de la precisión de las
estimaciones. Si estos intervalos son estrechos, la variable presenta un
efecto estable sobre el precio; si son amplios, podría haber mayor
incertidumbre.
- Conclusión: El bootstrapping complementa el análisis
tradicional (basado en supuestos de normalidad de los errores) al
proporcionar evidencia empírica de la fiabilidad de los coeficientes.
Esto fortalece la confianza en las conclusiones sobre la importancia
relativa de cada predictor y la estabilidad del modelo ante variaciones
en la muestra.
El presente informe aborda de manera integral el proceso de análisis y modelación del precio de la vivienda, desde la obtención y limpieza de datos hasta la selección de ofertas potenciales que cumplan con los límites de crédito establecidos. A continuación, se sintetizan los hallazgos y las recomendaciones principales:
En conclusión, la metodología aplicada permite explicar de forma consistente los factores que inciden en el precio de la vivienda y realizar predicciones confiables para apoyar la toma de decisiones. Estos resultados, reforzados por técnicas de selección de variables y validación, constituyen una herramienta valiosa para la empresa C&A, que puede optimizar su estrategia de ofertas y asesorar de manera más efectiva a sus clientes.