Este informe tiene como objetivo ayudar a María en la selección de viviendas basadas en las solicitudes recibidas para dos empleados internacionales. Para ello, realizamos un análisis exploratorio de datos, un modelo de regresión lineal múltiple, validaciones, predicciones y selección de ofertas. Se analiza por separado dos tipos de viviendas:
Primero, cargamos los datos de la base vivienda y
realizamos el preprocesamiento necesario.
# Cargar las librerías necesarias
library(paqueteMODELOS)
library(dplyr)
library(ggplot2)
library(tidyr)
library(plotly)
library(leaflet)
# Cargar los datos
data("vivienda")
# Verificar la estructura del conjunto de datos
str(vivienda)
## spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id : num [1:8322] 1147 1169 1350 5992 1212 ...
## $ zona : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
## $ piso : chr [1:8322] NA NA NA "02" ...
## $ estrato : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
## $ preciom : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
## $ areaconst : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
## $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
## $ banios : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
## $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
## $ tipo : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
## $ barrio : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
## $ longitud : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
## $ latitud : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
## - attr(*, "spec")=List of 3
## ..$ cols :List of 13
## .. ..$ id : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ zona : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ piso : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ estrato : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ preciom : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ areaconst : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ parqueaderos: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ banios : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ habitaciones: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ tipo : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ barrio : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ longitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ latitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## ..$ default: list()
## .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
## ..$ delim : chr ";"
## ..- attr(*, "class")= chr "col_spec"
## - attr(*, "problems")=<externalptr>
Realizamos el filtro inicial de las casas ubicadas en la Zona Norte para la vivienda 1, y los apartamentos en la Zona Sur para la vivienda 2.
# Filtrar casas en zona norte (Vivienda 1)
viviendas_norte <- vivienda %>%
filter(zona == "Zona Norte", tipo == "Casa")
# Filtrar apartamentos en zona sur (Vivienda 2)
viviendas_sur <- vivienda %>%
filter(zona == "Zona Sur", tipo == "Apartamento")
# Mostrar los primeros tres registros de cada base filtrada
head(viviendas_norte, 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>
head(viviendas_sur, 3)
## # A tibble: 3 × 13
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 5098 Zona S… 05 4 290 96 1 2 3
## 2 698 Zona S… 02 3 78 40 1 1 2
## 3 8199 Zona S… <NA> 6 875 194 2 5 3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
Mostramos un mapa con las propiedades filtradas para verificar si están ubicadas correctamente en la Zona Norte y Zona Sur.
# Mapa para Zona Norte
mapa_norte <- leaflet(viviendas_norte) %>%
addTiles() %>%
addMarkers(lng = ~longitud, lat = ~latitud, popup = ~paste("Precio:", preciom, "millones"))
# Mapa para Zona Sur
mapa_sur <- leaflet(viviendas_sur) %>%
addTiles() %>%
addMarkers(lng = ~longitud, lat = ~latitud, popup = ~paste("Precio:", preciom, "millones"))
# Mostrar ambos mapas
mapa_norte
mapa_sur
A continuación, realizamos un análisis exploratorio para identificar
la correlación entre la variable dependiente (preciom) y
otras variables importantes como el área construida, el número de baños,
parqueaderos, y habitaciones.
# Seleccionar variables relevantes para el análisis
correlacion_norte <- viviendas_norte %>%
select(preciom, areaconst, parqueaderos, banios, habitaciones)
correlacion_sur <- viviendas_sur %>%
select(preciom, areaconst, parqueaderos, banios, habitaciones)
# Correlación para zona norte
cor_norte <- cor(correlacion_norte, use = "complete.obs")
cor_norte
## preciom areaconst parqueaderos banios habitaciones
## preciom 1.0000000 0.6853915 0.4116620 0.5086427 0.3650859
## areaconst 0.6853915 1.0000000 0.3069709 0.4574766 0.4206897
## parqueaderos 0.4116620 0.3069709 1.0000000 0.3918638 0.2413962
## banios 0.5086427 0.4574766 0.3918638 1.0000000 0.5903821
## habitaciones 0.3650859 0.4206897 0.2413962 0.5903821 1.0000000
# Correlación para zona sur
cor_sur <- cor(correlacion_sur, use = "complete.obs")
cor_sur
## preciom areaconst parqueaderos banios habitaciones
## preciom 1.0000000 0.7407150 0.6934386 0.7111289 0.2957800
## areaconst 0.7407150 1.0000000 0.5783506 0.6639216 0.4073401
## parqueaderos 0.6934386 0.5783506 1.0000000 0.5563189 0.2367067
## banios 0.7111289 0.6639216 0.5563189 1.0000000 0.5204718
## habitaciones 0.2957800 0.4073401 0.2367067 0.5204718 1.0000000
Creamos gráficos interactivos para visualizar la relación entre las variables clave y el precio.
# Gráfico para zona norte
plot_norte <- plot_ly(viviendas_norte, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers',
marker = list(size = 10, color = ~banios, colorscale = 'Viridis', showscale = TRUE)) %>%
layout(title = "Relación Área Construida vs Precio (Zona Norte)", xaxis = list(title = "Área Construida"), yaxis = list(title = "Precio (millones)"))
# Gráfico para zona sur
plot_sur <- plot_ly(viviendas_sur, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers',
marker = list(size = 10, color = ~banios, colorscale = 'Viridis', showscale = TRUE)) %>%
layout(title = "Relación Área Construida vs Precio (Zona Sur)", xaxis = list(title = "Área Construida"), yaxis = list(title = "Precio (millones)"))
# Mostrar los gráficos
plot_norte
plot_sur
Creamos el modelo de regresión lineal múltiple con las variables:
areaconst, estrato, parqueaderos,
banios, y habitaciones.
# Asegurar que estrato es un factor
viviendas_norte$estrato <- factor(viviendas_norte$estrato)
viviendas_sur$estrato <- factor(viviendas_sur$estrato)
# Modelo para Zona Norte (Vivienda 1)
modelo_norte <- lm(preciom ~ areaconst + estrato + parqueaderos + banios + habitaciones, data = viviendas_norte)
summary(modelo_norte)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios +
## habitaciones, data = viviendas_norte)
##
## Residuals:
## Min 1Q Median 3Q Max
## -790.71 -74.72 -18.93 46.54 991.70
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 11.71883 27.15751 0.432 0.66631
## areaconst 0.68098 0.05283 12.890 < 2e-16 ***
## estrato4 80.91006 24.55085 3.296 0.00106 **
## estrato5 147.53872 22.70871 6.497 2.29e-10 ***
## estrato6 281.68942 37.33161 7.546 2.74e-13 ***
## parqueaderos 24.22922 5.86635 4.130 4.36e-05 ***
## banios 18.09024 7.62857 2.371 0.01816 *
## habitaciones 7.17906 5.69802 1.260 0.20839
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 154.9 on 427 degrees of freedom
## (287 observations deleted due to missingness)
## Multiple R-squared: 0.607, Adjusted R-squared: 0.6006
## F-statistic: 94.24 on 7 and 427 DF, p-value: < 2.2e-16
# Modelo para Zona Sur (Vivienda 2)
modelo_sur <- lm(preciom ~ areaconst + estrato + parqueaderos + banios + habitaciones, data = viviendas_sur)
summary(modelo_sur)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios +
## habitaciones, data = viviendas_sur)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1058.69 -39.21 0.38 36.96 898.14
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -28.38462 12.93336 -2.195 0.02828 *
## areaconst 1.28595 0.05105 25.189 < 2e-16 ***
## estrato4 30.40026 9.55717 3.181 0.00149 **
## estrato5 50.88889 9.61940 5.290 1.33e-07 ***
## estrato6 204.40443 11.17300 18.294 < 2e-16 ***
## parqueaderos 62.13696 3.79229 16.385 < 2e-16 ***
## banios 41.95467 3.24893 12.913 < 2e-16 ***
## habitaciones -17.10675 3.70357 -4.619 4.06e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 92.52 on 2373 degrees of freedom
## (406 observations deleted due to missingness)
## Multiple R-squared: 0.7762, Adjusted R-squared: 0.7755
## F-statistic: 1175 on 7 and 2373 DF, p-value: < 2.2e-16
Verificamos los supuestos de normalidad, homocedasticidad y multicolinealidad para ambos modelos.
# Validación de supuestos del modelo para la Zona Norte
par(mfrow = c(2, 2))
plot(modelo_norte)
# Validación de supuestos del modelo para la Zona Sur
par(mfrow = c(2, 2))
plot(modelo_sur)
Usamos el modelo ajustado para predecir el precio de una vivienda en la Zona Norte con las características dadas en la solicitud.
# Características de la vivienda 1 (Casa en zona norte)
vivienda1 <- data.frame(areaconst = 200, estrato = factor(4), parqueaderos = 1, banios = 2, habitaciones = 4)
# Predicción del precio
prediccion_vivienda1 <- predict(modelo_norte, newdata = vivienda1)
prediccion_vivienda1
## 1
## 317.9507
A continuación, buscamos las mejores ofertas para la vivienda 1 que cumplan con el límite del crédito preaprobado (350 millones).
# Filtrar las viviendas dentro del presupuesto para vivienda 1
ofertas_vivienda1 <- viviendas_norte %>%
filter(preciom <= 350) %>%
arrange(preciom) %>%
head(5)
# Mostrar las ofertas en un mapa
mapa_ofertas1 <- leaflet(ofertas_vivienda1) %>%
addTiles() %>%
addMarkers(lng = ~longitud, lat = ~latitud, popup = ~paste("Precio:", preciom, "millones"))
mapa_ofertas1
Repetimos los pasos de predicción y sugerencia de ofertas para la vivienda 2, con un crédito preaprobado de 850 millones.
# Características de la vivienda 2 (Apartamento en zona sur)
vivienda2 <- data.frame(areaconst = 300, estrato = factor(6), parqueaderos = 3, banios = 3, habitaciones = 5)
# Predicción del precio
prediccion_vivienda2 <- predict(modelo_sur, newdata = vivienda2)
prediccion_vivienda2
## 1
## 788.5467
# Filtrar las viviendas dentro del presupuesto para vivienda 2
ofertas_vivienda2 <- viviendas_sur %>%
filter(preciom <= 850) %>%
arrange(preciom) %>%
head(5)
# Mostrar las ofertas en un mapa
mapa_ofertas2 <- leaflet(ofertas_vivienda2) %>%
addTiles() %>%
addMarkers(lng = ~longitud, lat = ~latitud, popup = ~paste("Precio:", preciom, "millones"))
mapa_ofertas2
En este análisis, se ha modelado el mercado inmobiliario en Cali para asistir en la toma de decisiones de compra de viviendas. Se han hecho recomendaciones basadas en análisis estadísticos y se han generado sugerencias de ofertas potenciales. Ambos modelos de regresión ajustan adecuadamente los datos y permiten realizar predicciones confiables.