Introducción

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:

  1. Vivienda 1: Casas, Zona Norte.
  2. Vivienda 2: Apartamentos, Zona Sur.

Carga de Datos

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>

1. Filtro de la Base de Datos

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>

Mapa con las viviendas seleccionadas

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

2. Análisis Exploratorio de Datos

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.

Correlación entre las Variables

# 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

Gráficos de Correlación

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

3. Modelo de Regresión Lineal Múltiple

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

Interpretación de los Resultados del Modelo

  • Coeficientes significativos: Se identifican aquellos coeficientes con significancia estadística y se analizan sus efectos sobre el precio.
  • : Se discute la proporción de la variabilidad en el precio explicada por las variables predictoras en ambos modelos.

4. Validación de Supuestos del Modelo

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)

5. Predicción del Precio para la Vivienda 1

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

6. Sugerencia de Ofertas para Vivienda 1

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

7. Repetición de los Pasos 5 y 6 para Vivienda 2

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

Sugerencia de Ofertas para Vivienda 2

# 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

Conclusiones

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.