Análisis del Sector inmobiliario

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:

Texto Alternativo Bajo dicho escenario, en el presente ejercicio apoyaremos a la compañia C&A para responder a la solicitud presentada por la empresa internacional.

Análisis vivienda 1

Para comenzar con el análisis, empezamos cargando la data del sector vivienda en la ciudad de Cali. Igualmente, realizamos una exploración inicial de los datos para identificar qué variables se encuentran en ella.

library(paqueteMODELOS)
## Loading required package: boot
## Loading required package: broom
## Loading required package: GGally
## Loading required package: ggplot2
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
## Loading required package: gridExtra
## Loading required package: knitr
## Loading required package: summarytools
data("vivienda")
knitr::kable(head(vivienda, 10), caption = "Base de Datos VIVIENDA")
Base de Datos VIVIENDA
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1147 Zona Oriente NA 3 250 70 1 3 6 Casa 20 de julio -76.51168 3.43382
1169 Zona Oriente NA 3 320 120 1 2 3 Casa 20 de julio -76.51237 3.43369
1350 Zona Oriente NA 3 350 220 2 2 4 Casa 20 de julio -76.51537 3.43566
5992 Zona Sur 02 4 400 280 3 5 3 Casa 3 de julio -76.54000 3.43500
1212 Zona Norte 01 5 260 90 1 2 3 Apartamento acopi -76.51350 3.45891
1724 Zona Norte 01 5 240 87 1 3 3 Apartamento acopi -76.51700 3.36971
2326 Zona Norte 01 4 220 52 2 2 3 Apartamento acopi -76.51974 3.42627
4386 Zona Norte 01 5 310 137 2 3 4 Apartamento acopi -76.53105 3.38296
1209 Zona Norte 02 5 320 150 2 4 6 Casa acopi -76.51341 3.47968
1592 Zona Norte 02 5 780 380 2 3 3 Casa acopi -76.51674 3.48721

Luego de cargar la data inicial, procedemos a realizar un filtro en la base de datos para incluir solo los atributos que deseamos analizar para la vivienda tipo 1, incluyendo las viviendas que se ubiquen en el sector norte y sean casas.

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
vivienda_1 <- filter(vivienda, zona == "Zona Norte" & tipo == "Casa")
knitr::kable(head(vivienda_1, 3), caption = "Casas Norte")
Casas Norte
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1209 Zona Norte 02 5 320 150 2 4 6 Casa acopi -76.51341 3.47968
1592 Zona Norte 02 5 780 380 2 3 3 Casa acopi -76.51674 3.48721
4057 Zona Norte 02 6 750 445 NA 7 6 Casa acopi -76.52950 3.38527

Posterior a ello, ubicamos en un mapa a las viviendas que se ubican en el sector norte de Cali y cumplan con los criterios requeridos por la empresa.

library(leaflet)
vivienda_norte <- subset(vivienda, tipo=="Casa" & zona == "Zona Norte")

mapaNorte <- leaflet(vivienda_norte) %>%
  addTiles()  %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#F41309", radius = 2)

mapaNorte

Como se logra observar en la anterior figura, el mapa evidencia que existen algunos puntos que están por fuera de la zona norte en la ciudad de Cali. Una posible explicación para este comportamiento, se puede dar debido a que al momento de la creación de la base de datos se ingresaron algunos regitros erroneos, y por ello, en este momento se presentan dichas dificultades.

En virtud de ello, vamos a comprobar si existe el mismo error en otras dos zonas de la ciudad de Cali (centro y sur), para verificar el comportamiento de los datos.

vivienda_2 <- filter(vivienda, zona == "Zona Centro" & tipo == "Casa")
knitr::kable(head(vivienda_2, 3), caption = "Casas Centro")
Casas Centro
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
5298 Zona Centro 01 3 650 240 2 4 4 Casa alameda -76.53564 3.43521
5107 Zona Centro 02 4 400 460 NA 5 7 Casa alameda -76.53471 3.43627
5117 Zona Centro 02 3 380 290 NA 4 8 Casa alameda -76.53481 3.43712
vivienda_centro <- subset(vivienda, tipo=="Casa" & zona == "Zona Centro")

mapacentro <- leaflet(vivienda_centro) %>%
  addTiles()  %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#228CF5", radius = 2)

mapacentro

De igual manera, procedemos a graficar las casas de la zona sur.

vivienda_3 <- filter(vivienda, zona == "Zona Sur" & tipo == "Casa")
knitr::kable(head(vivienda_3, 3), caption = "Casas Sur")
Casas Sur
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
5992 Zona Sur 02 4 400 280 3 5 3 Casa 3 de julio -76.540 3.435
5157 Zona Sur 02 3 500 354 1 2 4 Casa alameda -76.535 3.437
5501 Zona Sur 02 3 175 102 NA 2 4 Casa alameda -76.537 3.435
vivienda_sur <- subset(vivienda, tipo=="Casa" & zona == "Zona Sur")

mapasur<- leaflet(vivienda_sur) %>%
  addTiles()  %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#F5E322", radius = 2)

mapasur

Como se logra observar en los diferentes mapas, se obtiene que en las diferentes zonas se encuentran puntos por fuera de los parámetros establecidos. Lo anterior, indica que en todas las zonas existen problemas de identificación de la latitud y longitud de los datos, lo cual genera que se ubiquen elementos por fuera de las zonas establecidas. Este resultado invita a realizar una depuración de la base de datos y a corregir los elementos, debido a que al momento de construir la base de datos, los propietarios pudieron haber identificado erróneamente su ubicación.

Este problema, generará que al momento de graficar los puntos en toda la ciudad de Cali, se obtenga puntos que se entremezclen en las diferentes zonas. Este resultado lo podemos observar en la siguiente gráfica.

vivienda_casas <- filter(vivienda, tipo == "Casa")
knitr::kable(head(vivienda_casas, 5), caption = "Casas")
Casas
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1147 Zona Oriente NA 3 250 70 1 3 6 Casa 20 de julio -76.51168 3.43382
1169 Zona Oriente NA 3 320 120 1 2 3 Casa 20 de julio -76.51237 3.43369
1350 Zona Oriente NA 3 350 220 2 2 4 Casa 20 de julio -76.51537 3.43566
5992 Zona Sur 02 4 400 280 3 5 3 Casa 3 de julio -76.54000 3.43500
1209 Zona Norte 02 5 320 150 2 4 6 Casa acopi -76.51341 3.47968
colores <- colorFactor(palette = c("#F5E322", "#228CF5", "#F41309", "#F58338", "#1FF589"), domain = vivienda_casas$zona)

mapa<- leaflet(vivienda_casas) %>%
  addTiles()  %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = ~colores(zona), radius = 3)

mapa

La anterior gráfica, comprueba la hipótesis de que existen puntos por fuera de cada zona. Lo anterior, requiere realizar una identificación correcta de la longitud y latitud para obtener una mejor clasificación de los datos. La depuración inicial de los datos contenidos en el dataset son fundamentales para otorgar una respuesta éxitosa a la compañía y que las potenciales viviendas que se puedan proponer contemplen los beneficios indicados en la carta de solicitud.

Análisis exploratorio de los datos

Al finalizar el análisis del subconjunto de las viviendas del sector Norte de la ciudad de Cali, procedemos a realizar un análisis de la correlación de la variable respuesta en función del área construida. Para ello, en un primero paso, vamos a establecer los principales estadísticos del Dataset obtenido.

summary(vivienda_casas)
##        id           zona               piso              estrato     
##  Min.   :   1   Length:3219        Length:3219        Min.   :3.000  
##  1st Qu.:1856   Class :character   Class :character   1st Qu.:3.000  
##  Median :4190   Mode  :character   Mode  :character   Median :5.000  
##  Mean   :3963                                         Mean   :4.485  
##  3rd Qu.:5862                                         3rd Qu.:5.000  
##  Max.   :8319                                         Max.   :6.000  
##                                                                      
##     preciom       areaconst       parqueaderos       banios      
##  Min.   :  77   Min.   :  30.0   Min.   : 1.00   Min.   : 0.000  
##  1st Qu.: 300   1st Qu.: 154.0   1st Qu.: 1.00   1st Qu.: 3.000  
##  Median : 430   Median : 240.0   Median : 2.00   Median : 4.000  
##  Mean   : 540   Mean   : 273.4   Mean   : 2.29   Mean   : 3.894  
##  3rd Qu.: 670   3rd Qu.: 350.0   3rd Qu.: 3.00   3rd Qu.: 5.000  
##  Max.   :1999   Max.   :1745.0   Max.   :10.00   Max.   :10.000  
##                                  NA's   :733                     
##   habitaciones       tipo              barrio             longitud     
##  Min.   : 0.00   Length:3219        Length:3219        Min.   :-76.59  
##  1st Qu.: 3.00   Class :character   Class :character   1st Qu.:-76.54  
##  Median : 4.00   Mode  :character   Mode  :character   Median :-76.53  
##  Mean   : 4.61                                         Mean   :-76.53  
##  3rd Qu.: 5.00                                         3rd Qu.:-76.52  
##  Max.   :10.00                                         Max.   :-76.46  
##                                                                        
##     latitud     
##  Min.   :3.333  
##  1st Qu.:3.383  
##  Median :3.413  
##  Mean   :3.415  
##  3rd Qu.:3.449  
##  Max.   :3.496  
## 

Al obtener los principales estadisticos del dataset, logramos identificar algunas medidas como la media, la moda y los mínimos, máximos y cuartiles de cada variable. Este procedimiento solo se obtuvo para el dataset que contenga el tipo de vivienda casa. De los estadísticos obtenidos, se debe reconocer que las variables baños y habitaciones presentan una situación particular porque se evidencia que el valor mínimo es cero, lo cual no tendría sentido, porque al menos las casas deberían tener un baño y habitación. A raíz de ello, vamos a identificar si esos valores se generan porque existen datos vacíos.

library(mice)
## 
## Attaching package: 'mice'
## The following object is masked from 'package:stats':
## 
##     filter
## The following objects are masked from 'package:base':
## 
##     cbind, rbind
md.pattern(vivienda_casas)

##      id zona estrato preciom areaconst banios habitaciones tipo barrio longitud
## 1626  1    1       1       1         1      1            1    1      1        1
## 860   1    1       1       1         1      1            1    1      1        1
## 339   1    1       1       1         1      1            1    1      1        1
## 394   1    1       1       1         1      1            1    1      1        1
##       0    0       0       0         0      0            0    0      0        0
##      latitud parqueaderos piso     
## 1626       1            1    1    0
## 860        1            1    0    1
## 339        1            0    1    1
## 394        1            0    0    2
##            0          733 1254 1987

La gráfica nos indica que existen algunos datos faltantes, ahora procedemos a ver en qué variables se encuentran esos valores ausentes.

missing_values <-sapply(vivienda_casas, function(x) sum(is.na(x))) 
knitr::kable(missing_values, caption = "Datos ausentes")
Datos ausentes
x
id 0
zona 0
piso 1254
estrato 0
preciom 0
areaconst 0
parqueaderos 733
banios 0
habitaciones 0
tipo 0
barrio 0
longitud 0
latitud 0

Con la anterior tabla, logramos observar que los datos ausentes se encuentran en las variables de parqueaderos y piso. Sin embargo, para aserguarnos de que no existan datos de habitaciones y banios con valores cero procedemos a realizar la siguiente verificación.

datos_cero_habitaciones <- vivienda_casas %>%
  filter(habitaciones == 0)

print(datos_cero_habitaciones)
## # A tibble: 45 × 13
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1   243 Zona … <NA>        3     190       435           NA      0            0
##  2  2013 Zona … <NA>        3     270       330           NA      3            0
##  3  2014 Zona … <NA>        3     270       330           NA      3            0
##  4  2741 Zona … <NA>        4     485       320           NA      4            0
##  5  3273 Zona … <NA>        3     400       324           NA      0            0
##  6  4095 Zona … <NA>        4     700       550           NA      6            0
##  7  4118 Zona … <NA>        5     620       450           NA      3            0
##  8  4329 Zona … <NA>        4     790       540           NA      6            0
##  9  4512 Zona … <NA>        4     620       300           NA      8            0
## 10  7245 Zona … <NA>        4    1200       752           NA      0            0
## # ℹ 35 more rows
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
datos_cero_banios <- vivienda_casas %>%
  filter(banios == 0)

print(datos_cero_banios)
## # A tibble: 31 × 13
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1   243 Zona … <NA>        3     190       435           NA      0            0
##  2  3273 Zona … <NA>        3     400       324           NA      0            0
##  3  7245 Zona … <NA>        4    1200       752           NA      0            0
##  4  4995 Zona … <NA>        3     420       235           NA      0            0
##  5  1816 Zona … <NA>        3     750       183            2      0            0
##  6  7509 Zona … 02          5    1200       660           NA      0            0
##  7  4393 Zona … 02          3     380       264           NA      0            0
##  8  1425 Zona … <NA>        5     395       220            1      0            0
##  9  3703 Zona … <NA>        6     395       140            2      0            3
## 10  3347 Zona … 02          4     950       444            1      0            0
## # ℹ 21 more rows
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Considerando los datos anteriores, observamos que si existen datos en las variables habitaciones y baños con valores iguales a cero. Sin embargo, dichos datos no tendrían sentidos porque cualquier casa debería tener por lo menos 1 baño y una habitación. A raíz de ello, procedemos a eliminar los datos que contienen estos datos para evitar algunos problemas en los modelos de regresión.

vivienda_casas_limpia <- vivienda_casas %>%
  filter(habitaciones != 0 & banios != 0)

knitr::kable(head(vivienda_casas_limpia), caption = "Base de datos limpia")
Base de datos limpia
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1147 Zona Oriente NA 3 250 70 1 3 6 Casa 20 de julio -76.51168 3.43382
1169 Zona Oriente NA 3 320 120 1 2 3 Casa 20 de julio -76.51237 3.43369
1350 Zona Oriente NA 3 350 220 2 2 4 Casa 20 de julio -76.51537 3.43566
5992 Zona Sur 02 4 400 280 3 5 3 Casa 3 de julio -76.54000 3.43500
1209 Zona Norte 02 5 320 150 2 4 6 Casa acopi -76.51341 3.47968
1592 Zona Norte 02 5 780 380 2 3 3 Casa acopi -76.51674 3.48721

Al realizar la limpieza de los datos del anterior paso, procedemos a continuar con el proceso de análisis de correlación de los datos. Antes de realizar dicho, procedimientos, analizaremos su normalidad y posteriormente, la correlación de los mismos.

options(repos = c(CRAN = "https://cran.rstudio.com"))
install.packages("plotly")
## 
##   There is a binary version available but the source version is later:
##        binary source needs_compilation
## plotly 4.10.3 4.10.4             FALSE
## installing the source package 'plotly'
library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
plot_ly(vivienda_casas_limpia, x = ~preciom, type = "histogram")%>%
  layout(title = "Histograma de precios")

El histograma nos permite observar que la mayor parte de los precios de las casas en la ciudad de Cali se concentran en el rango mínimo de 77 millones hasta 550 millones. En consecuencia, la gráfica normal tiene una distribución asimetrica hacia la izquierda.

Posterior a ello, procedemos con en análisis de la normal de la variable área construida.

plot_ly(vivienda_casas_limpia, x = ~areaconst, type = "histogram")%>%
  layout(title = "Histograma de área construida")

En relación con la gráfica normal del área construida de las casas, podemos observar que nuevamente la mayoría de los datos se concentran en la parte izquierda del histograma con la presencia de algunos datos distribuidos hacia la derecha. Sin embargo, en este caso, podemos identificar que la gráfica adquiera una distribución más normalizada porque la mayoría de los datos se concentran cerca a la media que es de 240 metros cuadrados.

plot_ly(vivienda_casas_limpia, x = ~estrato,y=~estrato, type = "bar")%>%
  layout(title = "Histograma del estrato")

En el anterior histograma, observamos que la mayoría de las casas de la ciudad de Cali se concentran en los estratos 5 y 6, sin embargo, también se logra evidenciar muchas viviendas en los estratos 3 y 4.

plot_ly(vivienda_casas_limpia, x = ~banios, type = "histogram")%>%
  layout(title = "Histograma del número de baños")

En relación con el histograma del número de baños, se evidencia que esta variable tiene una distribución que se acerca más a la normal de los datos donde la mayor parte de los datos se situan cerca de la media de este atributo que es igual a 4.

plot_ly(vivienda_casas_limpia, x = ~habitaciones, type = "histogram")%>%
  layout(title = "Histograma del número de habitaciones")

En relación con el número de habitaciones, se evidencia, nuevamente una distribución más cercana a la normalidad donde la mayor parte de los datos se concentran en la media de los datos que es igual a 4. Sin embargo, en este atributo se evidencia que existen varios datos por encima de 4, lo que podría indicar un sesgo hacia la derecha.

plot_ly(vivienda_casas_limpia, x = ~zona, type = "histogram")%>%
  layout(title = "Histograma de la zona")

Finalmente, en relación con las zonas de las casas, se logra identificar, que la mayor parte de ellas están en la zona sur, seguidos de la zona norte. Posterior a ello, procedemos a realizar el análisis de correlación de las variables de la siguiente manera:

library(GGally)

cor_1 <-vivienda_casas_limpia[,c("preciom","areaconst","banios","habitaciones")]
ggpairs(cor_1, title="GGally ") 

Teniendo en cuenta los resultados obtenidos previamente, se obtiene que las variables área construida y banios, son las que presentan la correlación más fuerte en relación con la variable precio. En efecto, con las variables área construida y precio, la correlación es de 0.654 y la correlación entre la variable precio y baños es de 0.583. Las correlaciones encontradas en las variables son medianamente altas, lo cual no puede generar problemas de multicolinealidad al momento de realizar la regresión lineal, sin embargo, dicha hipótesis inicial se verificará una vez se calcule el modelo y se evalúen sus supuestos.

Regresión lineal

datos_imputados <- vivienda_casas_limpia %>%
  mutate(parqueaderos = ifelse(is.na(parqueaderos), mean(parqueaderos, na.rm = TRUE), parqueaderos))

# Antes de realizar el modelo de RLM, se debe convertir la variable estrato.
datos_imputados$estrato <- factor(datos_imputados$estrato, levels = c("3", "4", "5", "6"))

# Convertir el factor a valores numéricos
datos_imputados$estrato_numerico <- as.numeric(datos_imputados$estrato)

modelo_casas = lm(preciom ~ areaconst + estrato_numerico + parqueaderos + habitaciones + banios, data = datos_imputados)
summary(modelo_casas)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato_numerico + parqueaderos + 
##     habitaciones + banios, data = datos_imputados)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1158.49  -107.27   -21.90    67.16  1125.07 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      -208.79651   14.36300 -14.537  < 2e-16 ***
## areaconst           0.73230    0.02575  28.441  < 2e-16 ***
## estrato_numerico  119.88279    4.25211  28.194  < 2e-16 ***
## parqueaderos       62.09064    3.13599  19.799  < 2e-16 ***
## habitaciones      -11.49023    2.67120  -4.302 1.75e-05 ***
## banios             41.11082    3.35766  12.244  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 197.7 on 3163 degrees of freedom
## Multiple R-squared:  0.6971, Adjusted R-squared:  0.6966 
## F-statistic:  1456 on 5 and 3163 DF,  p-value: < 2.2e-16

Teniendo en cuenta los resultados presentados en el modelo previamente, se logra identificar que todas las variables introducidas en el modelo son significativas debido a que el valor de la probabilidad es menor a 0.05, o mediante la regla rápida del t valor que sea igual o superior a 2.

Ahora bien, al analizar cada variable encontramos que los signos esperados de cada atributo es lógico, siendo la única excepción la variable habitaciones. Por ejemplo, el signo positivo del área construida es lógica, porque a mayor área se esperaría un mayor precio; igual relación se espera con el estrato, el número de parqueaderos, habitaciones y baños. Sin embargo, con la variable habitaciones se obtiene un relación negativa, está relación debe ser analizada porque es posible que un número excesivo de habitaciones pueda generar que el precio del bien inmueble disminuya. Así mismo, se podría explicar que un elevado número de habitaciones podría generar un mal aprovechamiento del área construida disminuyendo su valor comercial. No osbtante, este atributo debe ser analizado con cautela y realizar un mayor número de pruebas e hipótesis sobre su funcionamiento.

Ahora bien, en relación al coeficiente R, se observa que este adquiere un valor de 69.71%, lo que indica que el ajuste del modelo con las variables introducidas permiten explica el 69.71% de los cambios en el precio de las casas. Si bien es cierto, el modelo tiene una bondad de ajuste alta, es necesario, realizar algunos análisis que permitan tener un mejor ajuste de la estimación. De igual manera, es importamte tener en cuenta que el valor del R ajustado fue de 69.66%, cuyo valor es menor al R cuadrado es menos de un 2%, lo cual indica que al modelo no es necesario integrarle variables adicionales.

Con el objetivo de realizar un mejor proceso de estimación, procedemos a realizar algunas modelaciones adicionales. Por ello, ahora tendremos otra opción mediante la estimación paso a paso.

# se define el modelo  ingenuo  y= b0
modelo_b0<- lm(preciom ~ 1, data=datos_imputados)

#define model with all predictors
modelo_all <- lm(preciom ~ areaconst + estrato_numerico + parqueaderos + habitaciones + banios, data = datos_imputados)

# Se aplica el proceso forward stepwise regression
forward <- step(modelo_b0, direction='forward', scope=formula(modelo_all), trace=0)

# Visualización de los resultados 
knitr::kable(forward$anova)
Step Df Deviance Resid. Df Resid. Dev AIC
NA NA 3168 408277699 37289.36
+ estrato_numerico -1 182637708.3 3167 225639990 35412.12
+ areaconst -1 77363495.8 3166 148276495 34083.58
+ parqueaderos -1 18540220.4 3165 129736274 33662.28
+ banios -1 5353830.4 3164 124382444 33530.73
+ habitaciones -1 723387.2 3163 123659057 33514.25
summary(forward)
## 
## Call:
## lm(formula = preciom ~ estrato_numerico + areaconst + parqueaderos + 
##     banios + habitaciones, data = datos_imputados)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1158.49  -107.27   -21.90    67.16  1125.07 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      -208.79651   14.36300 -14.537  < 2e-16 ***
## estrato_numerico  119.88279    4.25211  28.194  < 2e-16 ***
## areaconst           0.73230    0.02575  28.441  < 2e-16 ***
## parqueaderos       62.09064    3.13599  19.799  < 2e-16 ***
## banios             41.11082    3.35766  12.244  < 2e-16 ***
## habitaciones      -11.49023    2.67120  -4.302 1.75e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 197.7 on 3163 degrees of freedom
## Multiple R-squared:  0.6971, Adjusted R-squared:  0.6966 
## F-statistic:  1456 on 5 and 3163 DF,  p-value: < 2.2e-16

Al realizar el modelo steppwise, se logra evidenciar los mismos resultados obtenidos en el modelo anterior. Para ello, procedemos a realizar una última modelación a través de un modelo logaritmico.

modelo_casas_log = lm(log(preciom) ~ log(areaconst) + estrato_numerico + log(parqueaderos) + log(habitaciones) + log(banios), data = datos_imputados)

modelo_casas_log_2 = lm(log(preciom) ~ log(areaconst) + estrato_numerico + parqueaderos + log(habitaciones) + banios, data = datos_imputados)

library(stargazer)
## 
## Please cite as:
##  Hlavac, Marek (2022). stargazer: Well-Formatted Regression and Summary Statistics Tables.
##  R package version 5.2.3. https://CRAN.R-project.org/package=stargazer
stargazer(modelo_casas, forward, modelo_casas_log, modelo_casas_log_2, type = "text")
## 
## ===================================================================================
##                                                 Dependent variable:                
##                                 ---------------------------------------------------
##                                          preciom                log(preciom)       
##                                     (1)          (2)          (3)          (4)     
## -----------------------------------------------------------------------------------
## areaconst                         0.732***     0.732***                            
##                                   (0.026)      (0.026)                             
##                                                                                    
## log(areaconst)                                              0.428***     0.421***  
##                                                             (0.011)      (0.011)   
##                                                                                    
## estrato_numerico                 119.883***   119.883***    0.243***     0.250***  
##                                   (4.252)      (4.252)      (0.006)      (0.006)   
##                                                                                    
## parqueaderos                     62.091***    62.091***                  0.053***  
##                                   (3.136)      (3.136)                   (0.004)   
##                                                                                    
## habitaciones                     -11.490***   -11.490***                           
##                                   (2.671)      (2.671)                             
##                                                                                    
## banios                           41.111***    41.111***                  0.072***  
##                                   (3.358)      (3.358)                   (0.005)   
##                                                                                    
## log(parqueaderos)                                           0.125***               
##                                                             (0.011)                
##                                                                                    
## log(habitaciones)                                           -0.041**     -0.032*   
##                                                             (0.018)      (0.018)   
##                                                                                    
## log(banios)                                                 0.276***               
##                                                             (0.017)                
##                                                                                    
## Constant                        -208.797***  -208.797***    2.788***     2.830***  
##                                   (14.363)     (14.363)     (0.049)      (0.050)   
##                                                                                    
## -----------------------------------------------------------------------------------
## Observations                       3,169        3,169        3,169        3,169    
## R2                                 0.697        0.697        0.798        0.800    
## Adjusted R2                        0.697        0.697        0.798        0.800    
## Residual Std. Error (df = 3163)   197.726      197.726       0.274        0.273    
## F Statistic (df = 5; 3163)      1,456.018*** 1,456.018*** 2,506.064*** 2,535.451***
## ===================================================================================
## Note:                                                   *p<0.1; **p<0.05; ***p<0.01

Ahora, al considerar los resultados obtenidos en el proceso de modelación, podemos evidenciar que los modelos 3 y 4 presentan un mejor funcionamiento que los primeros dos. A partir de ello, logramos identificar que en el modelo 3 se logró incrementar el R cuadrado al 79.8%, y las variables explicativas independientes fueron significativamente estadisticamente al 99% y al 95% (para el caso de las habitaciones). En el modelo 4 se logró incrementar un poco el R ajustado al 80%, pero se perdió significancia en la variable de habitaciones.

Al analizar los signos esperados de las variables, se obtiene un resultado similar a los modelos anteriores, sin embargo, se evidencia que al aplicar el logatirmo los coeficientes tienen un comportamiento más estable porque no se presentan valores de beta tan altos como en el estrato ni en la constante. En consecuencia, se puede afirmar que el modelo con logaritmo es más consistente, sin embargo, la elección final se realizará considerando las validación de los supuestos del modelo.

Análisis de los supuestos del modelo

Luego de realizar los procesos de estimación, se procede a validar los supuestos del modelo.

library(car)
## Loading required package: carData
## 
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
## 
##     recode
## The following object is masked from 'package:boot':
## 
##     logit
resultados_VIF <- data.frame(
  Modelo1 = vif(modelo_casas),
  Modelo2 = vif(forward),
  Modelo3 = vif(modelo_casas_log),
  Modelo4 = vif(modelo_casas_log_2)
)

print(resultados_VIF, caption = "VIF de Modelos")
##                   Modelo1  Modelo2  Modelo3  Modelo4
## areaconst        1.578617 1.739829 1.823131 1.841172
## estrato_numerico 1.739829 1.578617 1.828214 1.711792
## parqueaderos     1.337684 1.337684 1.271003 1.311851
## habitaciones     1.657605 2.130966 1.690562 1.679775
## banios           2.130966 1.657605 2.143910 2.092930

Al evaluar el factor de inflación de cada uno de los modelos sugeridos, logramos identificar que en ninguno de los modelos y de la variables se presenta problemas de multicolinealidad porque el valor encontrado en cada uno de ellos es inferior a 5.

par(mfrow = c(2, 2))
plot(modelo_casas, caption = "modelo 1")

plot(forward, caption = "modelo 2")

plot(modelo_casas_log, caption = "modelo 3")

plot(modelo_casas_log_2, caption = "modelo 4")

Como se puede observar en los gráficos, se visualiza que en los primeros modelos tanto en los cuantiles como el valores ajustados se observa un comportamiento que no permite evidenciar una dinámica aleatoria de los errores. En contraste, en los modelos 3 y 4 se logra observar un mejor ajuste de los datos a la línea media (theoretical quantiles) y se observa que los valores ajustados presentan una mayor dispersión.

En conclusión, se observa que los modelos 3 y 4 presentan un mejor comportamiento. Sin embargo, continuamos con el análisis y validación de los supuestos a través de las siguientes pruebas de hipótesis.

errores_Modelo1 = modelo_casas$residuals
errores_Modelo2 = forward$residuals
errores_Modelo3 = modelo_casas_log$residuals
errores_Modelo4 = modelo_casas_log_2$residuals

errores_modelos <- data.frame(
  errores_Modelo1 = modelo_casas$residuals,
  errores_Modelo2 = forward$residuals,
  errores_Modelo3 = modelo_casas_log$residuals,
  errores_Modelo4 = modelo_casas_log_2$residuals
)

knitr::kable(head(errores_modelos), caption = "Errores de los modelos")
Errores de los modelos
errores_Modelo1 errores_Modelo2 errores_Modelo3 errores_Modelo4
171.1707 171.1707 0.4441873 0.4402478
211.1955 211.1955 0.5438069 0.5103181
117.3646 117.3646 0.2995031 0.3010968
-193.3697 -193.3697 -0.2290460 -0.1959928
-160.3808 -160.3808 -0.2877372 -0.2593480
137.8292 137.8292 0.2565163 0.2904626

Luego de obtener los errores, procedemos a evaluar el supuesto de normalidad, teniendo en cuenta que la hipótesis nula establece que los errores presentan una distribución normal.

shapiro.test(errores_Modelo1)
## 
##  Shapiro-Wilk normality test
## 
## data:  errores_Modelo1
## W = 0.88392, p-value < 2.2e-16
shapiro.test(errores_Modelo2)
## 
##  Shapiro-Wilk normality test
## 
## data:  errores_Modelo2
## W = 0.88392, p-value < 2.2e-16
shapiro.test(errores_Modelo3)
## 
##  Shapiro-Wilk normality test
## 
## data:  errores_Modelo3
## W = 0.98512, p-value < 2.2e-16
shapiro.test(errores_Modelo4)
## 
##  Shapiro-Wilk normality test
## 
## data:  errores_Modelo4
## W = 0.98581, p-value < 2.2e-16

Como se logra observar en las pruebas de hipótesis, los resultados evidencian que los modelos cumplen con el supuesto de normalidad porque el valor p es menor a 0.05 y se acepta la hipótesis nula. A continuación, analizamos el supuesto de independencia de los errores.

library(lmtest)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
dwtest(modelo_casas)
## 
##  Durbin-Watson test
## 
## data:  modelo_casas
## DW = 1.5744, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
dwtest(forward)
## 
##  Durbin-Watson test
## 
## data:  forward
## DW = 1.5744, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
dwtest(modelo_casas_log)
## 
##  Durbin-Watson test
## 
## data:  modelo_casas_log
## DW = 1.6371, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
dwtest(modelo_casas_log_2)
## 
##  Durbin-Watson test
## 
## data:  modelo_casas_log_2
## DW = 1.6318, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0

Al observar los resultados obtenidos en cada uno de los modelos, se establece que los modelos no presentan problema de autocorrelación porque su valor p es menor a 0.05, con lo cual aceptamos la hipótesis nula de que los errores son independientes.

gqtest(modelo_casas)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo_casas
## GQ = 1.2149, df1 = 1579, df2 = 1578, p-value = 5.592e-05
## alternative hypothesis: variance increases from segment 1 to 2
gqtest(forward)
## 
##  Goldfeld-Quandt test
## 
## data:  forward
## GQ = 1.2149, df1 = 1579, df2 = 1578, p-value = 5.592e-05
## alternative hypothesis: variance increases from segment 1 to 2
gqtest(modelo_casas_log)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo_casas_log
## GQ = 1.0994, df1 = 1579, df2 = 1578, p-value = 0.02987
## alternative hypothesis: variance increases from segment 1 to 2
gqtest(modelo_casas_log_2)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo_casas_log_2
## GQ = 1.1017, df1 = 1579, df2 = 1578, p-value = 0.02721
## alternative hypothesis: variance increases from segment 1 to 2

Nuevamente, al analizar el supuesto de la varianza constante, logramos evidenciar que los modelos cumplen con este supuesto porque el p valor es menor al 0.05, con lo cual podemos aceptar la hipótesis nula de que la varianza de los errores es constante.

Al tener en cuenta que todos los modelos cumplen con los supuestos del MRLM, y considerando los resulados de cada uno de los modelos, se procede a escoger el modelo No. 3 como el más apropiado para realizar los siguientes procedimientos. Se decide escoger este modelo al reconocer que presentó unos valores de R y R ajustado mejores que los modelos 1 y 2 (y un poco inferiores al modelo 4), y presenta una significancia independiente (valor t) igual o superior al 95% en todas las variables explicativas.

Predicción de precios y potenciales ofertas.

Al finalizar con la modelación, se procede a realizar una predicción del precio de las vivienda y a responder el primer interrogante sugerido por la empresa a la compañia C&A.

# Convertir 'estrato_numerico' a numérico si aún no lo está
vivienda_casas_limpia$estrato <- as.numeric(as.character(vivienda_casas_limpia$estrato))

# Crear un dataframe con las condiciones
requerimientos_1 <- data.frame(
estrato_numerico=c(4,5),
areaconst=c(200,200),
parqueaderos=c(1,1),
banios=c(2,2),
habitaciones=c(4,4),
preciom = c(0, 350)
)

requerimientos_1
##   estrato_numerico areaconst parqueaderos banios habitaciones preciom
## 1                4       200            1      2            4       0
## 2                5       200            1      2            4     350
# Realizar la predicción
predicciones_log <- predict(modelo_casas_log, newdata = requerimientos_1, interval = "confidence")

predicciones_exp <- exp(predicciones_log)

print(predicciones_exp)
##        fit      lwr      upr
## 1 474.0213 457.4033 491.2431
## 2 604.6646 577.5946 633.0034

Los anteriores resulados nos evidencian el precio promedio utilizando como resultado el modelo logaritmico. De acuerdo con lo anterior, podemos observar que el valor de las casas en el norte de Cali con los requerimientos necesarios están entre 474 y 604 millones.

Casa <- filter(vivienda_casas_limpia, areaconst >= 200, parqueaderos >= 1, banios >= 2, habitaciones >= 4, zona == "Zona Norte", estrato >= 4, estrato <= 5, preciom <= 350)

min(Casa$preciom)
## [1] 230
max(Casa$preciom)
## [1] 350
cinco_aleatorios <- Casa %>% sample_n(5)
print(cinco_aleatorios)
## # A tibble: 5 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1270 Zona N… <NA>        5     350       203            2      2            5
## 2  7470 Zona N… 02          4     340       264            2      5            7
## 3  1822 Zona N… <NA>        4     340       295            2      2            4
## 4  1943 Zona N… <NA>        5     350       346            1      2            4
## 5  4483 Zona N… 02          5     342       250            1      4            6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Con los datos anteriores, se obtienen los cincos datos requeridos para la organización y con los requerimientos necesarios.

cinco_aleatorios <- Casa %>% sample_n(5)

mapaCasas <- leaflet(cinco_aleatorios) %>%
  addTiles() %>%
   setView(lng =  -76.51595234451665, lat = 3.436834062816008, zoom = 12)  %>%
  addCircleMarkers(lng = cinco_aleatorios$longitud,
                   lat = cinco_aleatorios$latitud,
                   label = as.character(paste0(cinco_aleatorios$tipo, " est:", cinco_aleatorios$estrato, " Precio:",cinco_aleatorios$preciom, "'000.000", " Pisos:", cinco_aleatorios$piso, " Parqueaderos: ", cinco_aleatorios$parqueaderos)), 
                   stroke = FALSE, 
                   fillOpacity = 0.5,
                   radius = 8,
                   color = "#228CF5"
                   )

mapaCasas 

Con los datos anteriores, podemos ubicar en el mapa cinco potenciales viviendas paradar respuesta a los requerimientos de la organización. Tal y como se establece en el mapa anterior y la tabla precedente se puede verificar que las cinco viviendas identificadas cumplen con los requerimientos de la empresa y de sus empleados para su adquisición.

Análisis vivienda 2

Procedemos con el análisis de la segunda vivienda, la cual solo contiene el tipo de vivienda apartamento. Para ello, comenzamos generando un subset de la data inicial.

viviendaAPA <- filter(vivienda, zona == "Zona Norte" & tipo == "Apartamento")
knitr::kable(head(vivienda_2, 3), caption = "Apartamentos Norte")
Apartamentos Norte
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
5298 Zona Centro 01 3 650 240 2 4 4 Casa alameda -76.53564 3.43521
5107 Zona Centro 02 4 400 460 NA 5 7 Casa alameda -76.53471 3.43627
5117 Zona Centro 02 3 380 290 NA 4 8 Casa alameda -76.53481 3.43712

Posterior a ello, ubicamos en un mapa a las viviendas que se ubican en el sector norte de Cali y cumplan con los criterios requeridos por la empresa.

vivienda_norte_apa <- subset(vivienda, tipo=="Apartamento" & zona == "Zona Norte")

mapaNorteA1 <- leaflet(vivienda_norte_apa) %>%
  addTiles()  %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#F41309", radius = 2)

mapaNorteA1

Como ocurrió con el subset de las casas, se logra evidenciar que en el dataset se ubican apartamentos que están por fuera de la zona norte. Con lo anterior, logramos reconocer nuevamente que se han generado algunos errores en la ubicación de la latitud y longitud del dataset y esto explica la presencia de puntos por fuera de la zona requerida.

Nuevamente, procedemos a verificar si existen estos errores en otros dos puntos (centro y sur), para verificar el comportamiento de los datos.

viviendaAPA2 <- filter(vivienda, zona == "Zona Centro" & tipo == "Apartamento")
knitr::kable(head(viviendaAPA2, 3), caption = "Apartamentos Centro")
Apartamentos Centro
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
4654 Zona Centro 03 3 100 70.00 NA 2 3 Apartamento alameda -76.53200 3.45200
4408 Zona Centro 05 3 120 84.00 1 2 3 Apartamento alameda -76.53123 3.44011
4395 Zona Centro 04 3 125 66.76 NA 2 3 Apartamento bretaña -76.53111 3.44034
vivienda_centro_apa <- subset(vivienda, tipo=="Apartamento" & zona == "Zona Centro")

mapacentroapa <- leaflet(vivienda_centro_apa) %>%
  addTiles()  %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#228CF5", radius = 2)

mapacentroapa

De igual manera, procedemos a graficar los apartamentos de la zona sur.

viviendaAPA3 <- filter(vivienda, zona == "Zona Sur" & tipo == "CApartamento")
knitr::kable(head(viviendaAPA3, 3), caption = "Apartamentos Sur")
Apartamentos Sur
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
viviendaAPA3 <- subset(vivienda, tipo=="Apartamento" & zona == "Zona Sur")

mapasurapa<- leaflet(viviendaAPA3) %>%
  addTiles()  %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#F5E322", radius = 2)

mapasurapa

Como en el caso de las casas, se obtienen puntos en diferentes zonas de la ciudad. De igual manera, si graficamos los puntos en los diferentes puntos de Cali encontraremos puntos por fuera de las zonas establecidas.

vivienda_apartamentos <- filter(vivienda, tipo == "Apartamento")
knitr::kable(head(vivienda_casas, 5), caption = "Apartamentos")
Apartamentos
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1147 Zona Oriente NA 3 250 70 1 3 6 Casa 20 de julio -76.51168 3.43382
1169 Zona Oriente NA 3 320 120 1 2 3 Casa 20 de julio -76.51237 3.43369
1350 Zona Oriente NA 3 350 220 2 2 4 Casa 20 de julio -76.51537 3.43566
5992 Zona Sur 02 4 400 280 3 5 3 Casa 3 de julio -76.54000 3.43500
1209 Zona Norte 02 5 320 150 2 4 6 Casa acopi -76.51341 3.47968
colores <- colorFactor(palette = c("#F5E322", "#228CF5", "#F41309", "#F58338", "#1FF589"), domain = vivienda_apartamentos$zona)

mapaAPA<- leaflet(vivienda_apartamentos) %>%
  addTiles()  %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = ~colores(zona), radius = 3)

mapaAPA

La anterior gráfica, nos corrobora que los datos presentan inconsistencias debido a dos elementos: el error humano al momento de crear la base de datos; o la desactualización de los datos que puede generar que los mismos presenten valores en la longitud o latitud erroneos. Al igual que en el análisis de la casas, la depuración de la base de datos es fundamental para que al momento de proponer las potenciales viviendas solicitadas por la compañía cumplan con los requerimientos establecidos por ellos.

Análisis exploratorio de los datos

Al finalizar el análisis del subconjunto de los apartamentos del sector Sur de la ciudad de Cali, procedemos a realizar un análisis de la correlación de la variable respuesta en función del área construida. Para ello, en un primero paso, vamos a establecer los principales estadísticos del Dataset obtenido.

summary(vivienda_apartamentos)
##        id           zona               piso              estrato     
##  Min.   :   3   Length:5100        Length:5100        Min.   :3.000  
##  1st Qu.:2180   Class :character   Class :character   1st Qu.:4.000  
##  Median :4158   Mode  :character   Mode  :character   Median :5.000  
##  Mean   :4284                                         Mean   :4.727  
##  3rd Qu.:6556                                         3rd Qu.:6.000  
##  Max.   :8317                                         Max.   :6.000  
##                                                                      
##     preciom         areaconst      parqueaderos        banios     
##  Min.   :  58.0   Min.   : 35.0   Min.   : 1.000   Min.   :0.000  
##  1st Qu.: 175.0   1st Qu.: 68.0   1st Qu.: 1.000   1st Qu.:2.000  
##  Median : 279.0   Median : 90.0   Median : 1.000   Median :2.000  
##  Mean   : 366.9   Mean   :112.8   Mean   : 1.568   Mean   :2.617  
##  3rd Qu.: 430.0   3rd Qu.:130.0   3rd Qu.: 2.000   3rd Qu.:3.000  
##  Max.   :1950.0   Max.   :932.0   Max.   :10.000   Max.   :8.000  
##                                   NA's   :869                     
##   habitaciones       tipo              barrio             longitud     
##  Min.   :0.000   Length:5100        Length:5100        Min.   :-76.59  
##  1st Qu.:3.000   Class :character   Class :character   1st Qu.:-76.54  
##  Median :3.000   Mode  :character   Mode  :character   Median :-76.53  
##  Mean   :2.971                                         Mean   :-76.53  
##  3rd Qu.:3.000                                         3rd Qu.:-76.52  
##  Max.   :9.000                                         Max.   :-76.46  
##                                                                        
##     latitud     
##  Min.   :3.334  
##  1st Qu.:3.380  
##  Median :3.419  
##  Mean   :3.419  
##  3rd Qu.:3.453  
##  Max.   :3.498  
## 

Al obtener los principales estadisticos del dataset, logramos identificar algunas medidas como la media, la moda y los mínimos, máximos y cuartiles de cada variable. Este procedimiento solo se obtuvo para el dataset que contenga el tipo de vivienda apartamento. Al igual que con el subset de las casas, se debe reconocer que las variables baños y habitaciones presentan una situaación particular porque se evidencia que el valor mínimo es cero, lo cual no tendría sentido, porque al menos los apartamentos deberían tener un baño y habitación. A raíz de ello, vamos a identificar si esos valores se generan porque existen datos vacíos.

md.pattern(vivienda_apartamentos)

##      id zona estrato preciom areaconst banios habitaciones tipo barrio longitud
## 3182  1    1       1       1         1      1            1    1      1        1
## 1049  1    1       1       1         1      1            1    1      1        1
## 537   1    1       1       1         1      1            1    1      1        1
## 332   1    1       1       1         1      1            1    1      1        1
##       0    0       0       0         0      0            0    0      0        0
##      latitud parqueaderos piso     
## 3182       1            1    1    0
## 1049       1            1    0    1
## 537        1            0    1    1
## 332        1            0    0    2
##            0          869 1381 2250

La gráfica nos indica que existen algunos datos faltantes, ahora procedemos a ver en qué variables se encuentran los datos ausentes.

missing_values_apa <-sapply(vivienda_apartamentos, function(x) sum(is.na(x))) 
knitr::kable(missing_values_apa, caption = "Datos ausentes")
Datos ausentes
x
id 0
zona 0
piso 1381
estrato 0
preciom 0
areaconst 0
parqueaderos 869
banios 0
habitaciones 0
tipo 0
barrio 0
longitud 0
latitud 0

Los datos faltantes están en las variables piso y parqueadero. Sin embargo, existen valores cero en estas dos variables, los cuales necesitamos eliminar para que no se generen problemas de análisis con el MRLM.

datos_cero_habitaciones_apa <- vivienda_apartamentos %>%
  filter(habitaciones == 0)

print(datos_cero_habitaciones_apa)
## # A tibble: 21 × 13
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1  6839 Zona … <NA>        6     900       250            2      0            0
##  2  1523 Zona … 02          5     195        35           NA      1            0
##  3  3062 Zona … 06          4     285        90           NA      4            0
##  4  1524 Zona … 10          5     330        91           NA      3            0
##  5  5392 Zona … 12          4     650       270           NA      4            0
##  6  3458 Zona … 07          5     415       118            2      5            0
##  7  6173 Zona … 09          5     380       120            2      0            0
##  8  2532 Zona … 01          4     275        96            2      2            0
##  9  3997 Zona … 12          4     240        73            1      2            0
## 10  1594 Zona … 03          4     152        60            1      2            0
## # ℹ 11 more rows
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
datos_cero_banios_apa <- vivienda_apartamentos %>%
  filter(banios == 0)

print(datos_cero_banios_apa)
## # A tibble: 14 × 13
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1  6839 Zona … <NA>        6     900       250            2      0            0
##  2  1898 Zona … <NA>        4     220        68           NA      0            3
##  3  6173 Zona … 09          5     380       120            2      0            0
##  4  3553 Zona … 05          5     320        92           NA      0            3
##  5  5908 Zona … <NA>        5     950       280           10      0            0
##  6  7011 Zona … <NA>        4     160        76           NA      0            0
##  7  7132 Zona … 02          5     310        80            1      0            1
##  8  7884 Zona … 03          5     380       108           NA      0            0
##  9  7522 Zona … <NA>        3     148        87           NA      0            0
## 10  6513 Zona … 07          5     640       167            2      0            3
## 11  4526 Zona … 02          6    1000       520           NA      0            5
## 12  4915 Zona … <NA>        4     160        84            1      0            0
## 13  1356 Zona … 02          3     320       310           NA      0            0
## 14  8007 Zona … <NA>        6     410       129           NA      0            0
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Considerando los datos anteriores, observamos que si existen datos en las variables habitaciones y baños con valores iguales a cero. Sin embargo, dichos datos no tendrían sentido porque el apartamento debería tener por lo menos 1 baño y una habitación. En consecuencia, los procedemos a eliminar del subconjunto de datos creado.

vivienda_apartamentos_limpia <- vivienda_apartamentos %>%
  filter(habitaciones != 0 & banios != 0)

knitr::kable(head(vivienda_apartamentos_limpia), caption = "Base de datos de Apartamentos limpia")
Base de datos de Apartamentos limpia
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1212 Zona Norte 01 5 260 90 1 2 3 Apartamento acopi -76.51350 3.45891
1724 Zona Norte 01 5 240 87 1 3 3 Apartamento acopi -76.51700 3.36971
2326 Zona Norte 01 4 220 52 2 2 3 Apartamento acopi -76.51974 3.42627
4386 Zona Norte 01 5 310 137 2 3 4 Apartamento acopi -76.53105 3.38296
7497 Zona Norte 02 6 520 98 2 2 2 Apartamento acopi -76.54999 3.43505
5424 Zona Norte 03 4 320 108 2 3 3 Apartamento acopi -76.53638 3.40770

Al tener la base de datos limpia, procedemos a realizar la exploración inicial de los datos, teniendo en cuenta su normalidad y correlación.

options(repos = c(CRAN = "https://cran.rstudio.com"))
plot_ly(vivienda_apartamentos_limpia, x = ~preciom, type = "histogram")%>%
  layout(title = "Histograma de precios - apartamentos")

En relación con el precio, los datos se agrupan hacia la izquierda especialmente en el rango de 60 a 420 millones. Se debe resaltar que la mayor parte de los precios de los apartamentos se concentran sobre la media que es de 279 millones. Ahora continuamos con el análisis del área construida.

plot_ly(vivienda_apartamentos_limpia, x = ~areaconst, type = "histogram")%>%
  layout(title = "Histograma de área construida - apartamentos")

Con relación a la variable de área construida, nuevamente evidenciamos una distribución de los datos que se concentra en el lado izquierdo. Aqui es importante resaltar que la mayoría de los datos se concentran por debajo de la media del área de construcción que es de 90 metros.

plot_ly(vivienda_apartamentos_limpia, x = ~estrato,y=~estrato, type = "bar")%>%
  layout(title = "Histograma del estrato - apartamentos")

En el anterior histograma, observamos que la mayoría de los apartamentos de la ciudad de Cali se concentran en los estratos 5 y 6. En menor medida están en el estrato 4 y por último el estrato 3.

plot_ly(vivienda_apartamentos_limpia, x = ~banios, type = "histogram")%>%
  layout(title = "Histograma del número de baños - apartamentos")

En la anterior gráfica observamos una distribución más cercana a la normal donde la mayoría de los datos se concentran en el valor medio del número de baños que es igual a 2.

plot_ly(vivienda_apartamentos_limpia, x = ~habitaciones, type = "histogram")%>%
  layout(title = "Histograma del número de habitaciones - apartamentos")

En relación con el número de habitaciones, se evidencia, nuevamente una distribución similar a la normalidad donde la mayor parte de los datos se concentran en la media de los datos que es igual a 3.

plot_ly(vivienda_apartamentos_limpia, x = ~zona, type = "histogram")%>%
  layout(title = "Histograma de la zona - apartamentos")

Finalmente, en relación con las zonas de las casas, se logra identificar, que la mayor parte de ellas están en la zona sur, seguidos de la zona norte.

Luego de finalizar el análisis de normalidad de los datos, procedemos a identificar la correlación de los datos en el subset de viviendas tipo apartamento.

cor_1_apa <-vivienda_apartamentos_limpia[,c("preciom","areaconst","banios","habitaciones")]
ggpairs(cor_1_apa, title="Correlación apartamentos") 

Considerando los resultados anteriores, podemos identificar que las variables áreas construidas y baños presentan un alto nivel de correlación con el precio de los apartamentos con un 0.83 y un 0.75 respectivamente. Con la variable habitaciones se evidencia un nivel de correlación bajo. El alto nivel de correlación con las primeras variables puede generar algunos problemas de multicolinealidad al momento de realizar el MRLM, sin embargo, dicha afirmación solo se podrá verificar con la validación de los supuestos del modelo.

Regresión lineal

datos_imputados_apa <- vivienda_apartamentos_limpia %>%
  mutate(parqueaderos = ifelse(is.na(parqueaderos), mean(parqueaderos, na.rm = TRUE), parqueaderos))

# Antes de realizar el modelo de RLM, se debe convertir la variable estrato.
datos_imputados_apa$estrato <- factor(datos_imputados_apa$estrato, levels = c("3", "4", "5", "6"))

# Convertir el factor a valores numéricos
datos_imputados_apa$estrato_numerico <- as.numeric(datos_imputados_apa$estrato)

modelo_apartamentos = lm(preciom ~ areaconst + estrato_numerico + parqueaderos + habitaciones + banios, data = datos_imputados_apa)
summary(modelo_apartamentos)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato_numerico + parqueaderos + 
##     habitaciones + banios, data = datos_imputados_apa)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1760.48   -54.19    -1.83    47.54  1003.83 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      -176.66157   10.27856  -17.19   <2e-16 ***
## areaconst           2.08407    0.04396   47.41   <2e-16 ***
## estrato_numerico   58.87480    2.49077   23.64   <2e-16 ***
## parqueaderos       88.02545    3.66490   24.02   <2e-16 ***
## habitaciones      -41.69516    3.38391  -12.32   <2e-16 ***
## banios             51.40802    3.02931   16.97   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 129.8 on 5068 degrees of freedom
## Multiple R-squared:  0.799,  Adjusted R-squared:  0.7988 
## F-statistic:  4028 on 5 and 5068 DF,  p-value: < 2.2e-16

Teniendo en cuenta los resultados presentados en el modelo previamente, se logra identificar que todas las variables introducidas en el modelo son significativas debido a que el valor de la probabilidad es menor a 0.05, o mediante la regla rápida del t valor que sea igual o superior a 2.

Ahora bien, al realizar el análisis de cada variable encontramos que los signos esperados de cada atributo es lógico, siendo la única excepción la variable habitaciones. Por ejemplo, el signo positivo del área construida es lógico, porque a mayor área se esperaría un mayor precio; igual relación se espera con el estrato, el número de parqueaderos, habitaciones y baños. Sin embargo, con la variable habitaciones se obtiene un relación negativa, está relación debe ser analizada con cuidado porque es posible que un número excesivo de habitaciones pueda generar que el precio del bien inmueble disminuya.

Ahora bien, en relación al coeficiente R, se observa que este adquiere un valor de 79.9%, lo que indica que el ajuste del modelo con las variables introducidas permiten explica el 79.9% de los cambios en el precio de los apartamentos, a pesar del valor alto, se debería explorar otras opciones para mejorar el valor de este indicador. De igual manera, es importamte tener en cuenta que el valor del R ajustado fue de 79.88%, cuyo valor es menor al R cuadrado es menos de un 2%, lo cual indica que al modelo no es necesario integrarle variables adicionales.

Con el objetivo de realizar un mejor proceso de estimación, procedemos a realizar algunas modelaciones adicionales. Por ello, realizaremos la estimación paso a paso.

modelo_b0_apa<- lm(preciom ~ 1, data=datos_imputados_apa)

modelo_all_apa <- lm(preciom ~ areaconst + estrato_numerico + parqueaderos + habitaciones + banios, data = datos_imputados_apa)

forward_apa <- step(modelo_b0_apa, direction='forward', scope=formula(modelo_all_apa), trace=0)

knitr::kable(forward_apa$anova)
Step Df Deviance Resid. Df Resid. Dev AIC
NA NA 5073 424980908 57519.19
+ areaconst -1 295692993 5072 129287916 51483.12
+ estrato_numerico -1 25695926 5071 103591989 50360.81
+ parqueaderos -1 12588773 5070 91003216 49705.40
+ banios -1 3001296 5069 88001920 49537.24
+ habitaciones -1 2559588 5068 85442332 49389.47
summary(forward_apa)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato_numerico + parqueaderos + 
##     banios + habitaciones, data = datos_imputados_apa)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1760.48   -54.19    -1.83    47.54  1003.83 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      -176.66157   10.27856  -17.19   <2e-16 ***
## areaconst           2.08407    0.04396   47.41   <2e-16 ***
## estrato_numerico   58.87480    2.49077   23.64   <2e-16 ***
## parqueaderos       88.02545    3.66490   24.02   <2e-16 ***
## banios             51.40802    3.02931   16.97   <2e-16 ***
## habitaciones      -41.69516    3.38391  -12.32   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 129.8 on 5068 degrees of freedom
## Multiple R-squared:  0.799,  Adjusted R-squared:  0.7988 
## F-statistic:  4028 on 5 and 5068 DF,  p-value: < 2.2e-16

Al realizar el modelo steppwise, se logra evidenciar los mismos resultados obtenidos en el modelo anterior. Para ello, procedemos a realizar una última modelación a través de un modelo logaritmico.

modelo_apartamentos_log = lm(log(preciom) ~ log(areaconst) + estrato_numerico + log(parqueaderos) + log(habitaciones) + log(banios), data = datos_imputados_apa)

modelo_apartamentos_log_2 = lm(log(preciom) ~ log(areaconst) + estrato_numerico + parqueaderos + log(habitaciones) + banios, data = datos_imputados_apa)

stargazer(modelo_apartamentos, modelo_apartamentos_log, modelo_apartamentos_log_2, type = "text")
## 
## ======================================================================
##                                          Dependent variable:          
##                                 --------------------------------------
##                                   preciom          log(preciom)       
##                                     (1)          (2)          (3)     
## ----------------------------------------------------------------------
## areaconst                         2.084***                            
##                                   (0.044)                             
##                                                                       
## log(areaconst)                                 0.695***     0.670***  
##                                                (0.013)      (0.013)   
##                                                                       
## estrato_numerico                 58.875***     0.236***     0.245***  
##                                   (2.491)      (0.005)      (0.005)   
##                                                                       
## parqueaderos                     88.025***                  0.078***  
##                                   (3.665)                   (0.006)   
##                                                                       
## habitaciones                     -41.695***                           
##                                   (3.384)                             
##                                                                       
## banios                           51.408***                  0.093***  
##                                   (3.029)                   (0.005)   
##                                                                       
## log(parqueaderos)                              0.129***               
##                                                (0.011)                
##                                                                       
## log(habitaciones)                             -0.187***    -0.181***  
##                                                (0.016)      (0.016)   
##                                                                       
## log(banios)                                    0.248***               
##                                                (0.013)                
##                                                                       
## Constant                        -176.662***    1.769***     1.755***  
##                                   (10.279)     (0.045)      (0.044)   
##                                                                       
## ----------------------------------------------------------------------
## Observations                       5,074        5,074        5,074    
## R2                                 0.799        0.880        0.881    
## Adjusted R2                        0.799        0.880        0.881    
## Residual Std. Error (df = 5068)   129.843       0.226        0.226    
## F Statistic (df = 5; 5068)      4,027.937*** 7,462.292*** 7,515.777***
## ======================================================================
## Note:                                      *p<0.1; **p<0.05; ***p<0.01

Ahora, al considerar los resultados obtenidos en el proceso de modelación, podemos evidenciar que los modelos 2 y 3 presentan un mejor funcionamiento que el primero. A partir de ello, logramos identificar que en el modelo 2 se logró incrementar el R cuadrado al 88%, y las variables explicativas independientes fueron significativamente estadisticamente al 99%. En el modelo 3, se logró incrementar un poco el R ajustado al 88.1% y se logró que todas las variables de forma independiente tuvieran una significancia del 99%.

Al analizar los signos esperados de las variables, se obtiene un resultado similar a los modelos anteriores, sin embargo, se evidencia que al aplicar el logatirmo los coeficientes tienen un comportamiento más estable porque no se presentan valores de beta tan altos como en el parqueadero ni en la constante. En consecuencia, se puede afirmar que el modelo con logaritmo es más consistente, sin embargo, la elección final se realizará considerando las validación de los supuestos del modelo de RLM.

Análisis de los supuestos del modelo

Luego de realizar los procesos de estimación, se procede a validar los supuestos del modelo.

resultados_VIF_apa <- data.frame(
  ModeloAPA1 = vif(modelo_apartamentos),
  ModeloAPA2 = vif(modelo_apartamentos_log),
  ModeloAPA3 = vif(modelo_apartamentos_log_2)
)

print(resultados_VIF_apa, caption = "VIF de Modelos - apartamentos")
##                  ModeloAPA1 ModeloAPA2 ModeloAPA3
## areaconst          2.742951   3.569482   3.861424
## estrato_numerico   1.786219   2.129846   2.022177
## parqueaderos       1.799019   1.644376   1.751925
## habitaciones       1.450540   1.406673   1.413237
## banios             3.105477   2.887572   3.209848

Al evaluar el factor de inflación de cada uno de los modelos sugeridos, logramos identificar que en ninguno de los modelos y de las variables se presenta problemas de multicolinealidad porque el valor encontrado en cada uno de ellos es inferior a 5. De los tres modelos seleccionados se podría decir que el modelo 1 y 2 presentan los mejores resultados.

par(mfrow = c(2, 2))
plot(modelo_apartamentos, caption = "modelo 1")

plot(modelo_apartamentos_log, caption = "modelo 2")

plot(modelo_apartamentos_log_2, caption = "modelo 3")

Al igual que en el modelo de las casas, los MRLM con los logaritmos presentan un mejor comportamiento permitiendo que los residuos tengan un comportamiento con mayor aleatoridad y un mejor ajuste de acuerdo a la media para disminuir su varianza. En este sentido, los modelos 2 y 3 presentan un comportamiento más estable que el modelo 1. A continuación, procedemos con el análisis y validación de los supuestos a través de pruebas de hipótesis.

errores_ModeloAPA1 = modelo_apartamentos$residuals
errores_ModeloAPA2 = modelo_apartamentos_log$residuals
errores_ModeloAPA3 = modelo_apartamentos_log_2$residuals

errores_modelos_apa <- data.frame(
  errores_ModeloAPA1 = modelo_apartamentos$residuals,
  errores_ModeloAPA2 = modelo_apartamentos_log$residuals,
  errores_ModeloAPA3 = modelo_apartamentos_log_2$residuals
)

knitr::kable(head(errores_modelos_apa), caption = "Errores de los modelos - apartamentos")
Errores de los modelos - apartamentos
errores_ModeloAPA1 errores_ModeloAPA2 errores_ModeloAPA3
6.714726 -0.0107061 -0.0096679
-58.441075 -0.1678919 -0.1604336
16.758792 0.3498645 0.3583662
-138.974945 -0.2633933 -0.2341554
61.446737 0.2219395 0.2300593
-51.357232 0.1156946 0.1502485

Luego de obtener los errores, procedemos a evaluar el supuesto de normalidad, teniendo en cuenta que la hipótesis nula establece que los errores presentan una distribución normal.

ks.test(errores_ModeloAPA1, "pnorm", mean = mean(errores_ModeloAPA1), sd = sd(errores_ModeloAPA1))
## Warning in ks.test.default(errores_ModeloAPA1, "pnorm", mean =
## mean(errores_ModeloAPA1), : ties should not be present for the
## Kolmogorov-Smirnov test
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  errores_ModeloAPA1
## D = 0.13772, p-value < 2.2e-16
## alternative hypothesis: two-sided
ks.test(errores_ModeloAPA2, "pnorm", mean = mean(errores_ModeloAPA2), sd = sd(errores_ModeloAPA2))
## Warning in ks.test.default(errores_ModeloAPA2, "pnorm", mean =
## mean(errores_ModeloAPA2), : ties should not be present for the
## Kolmogorov-Smirnov test
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  errores_ModeloAPA2
## D = 0.032783, p-value = 3.668e-05
## alternative hypothesis: two-sided
ks.test(errores_ModeloAPA3, "pnorm", mean = mean(errores_ModeloAPA3), sd = sd(errores_ModeloAPA3))
## Warning in ks.test.default(errores_ModeloAPA3, "pnorm", mean =
## mean(errores_ModeloAPA3), : ties should not be present for the
## Kolmogorov-Smirnov test
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  errores_ModeloAPA3
## D = 0.031515, p-value = 8.391e-05
## alternative hypothesis: two-sided

Como se logra observar en las pruebas de hipótesis, los resultados evidencian que los modelos cumplen con el supuesto de normalidad porque el valor p es menor a 0.05 y se acepta la hipótesis nula. A continuación, analizamos el supuesto de independencia de los errores.

dwtest(modelo_apartamentos)
## 
##  Durbin-Watson test
## 
## data:  modelo_apartamentos
## DW = 1.6584, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
dwtest(modelo_apartamentos_log)
## 
##  Durbin-Watson test
## 
## data:  modelo_apartamentos_log
## DW = 1.5788, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
dwtest(modelo_apartamentos_log_2)
## 
##  Durbin-Watson test
## 
## data:  modelo_apartamentos_log_2
## DW = 1.5779, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0

Al observar los resultados obtenidos en cada uno de los modelos, se establece que los modelos no presentan problema de autocorrelación porque su valor p es menor a 0.05, con lo cual aceptamos la hipótesis nula de que los errores son independientes.

gqtest(modelo_apartamentos)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo_apartamentos
## GQ = 1.5652, df1 = 2531, df2 = 2531, p-value < 2.2e-16
## alternative hypothesis: variance increases from segment 1 to 2
gqtest(modelo_apartamentos_log)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo_apartamentos_log
## GQ = 1.0276, df1 = 2531, df2 = 2531, p-value = 0.2471
## alternative hypothesis: variance increases from segment 1 to 2
gqtest(modelo_apartamentos_log_2)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo_apartamentos_log_2
## GQ = 1.0114, df1 = 2531, df2 = 2531, p-value = 0.3876
## alternative hypothesis: variance increases from segment 1 to 2

Al analizar el supuesto de la varianza constante, logramos evidenciar que el modelo 1 cumple con este supuesto porque el p valor es menor al 0.05, con lo cual podemos aceptar la hipótesis nula de que la varianza de los errores es constante. En contraste, los modelos 2 y 3 no cumplen con este supuesto porque su valor p es mayor a 0.05, con los cual negamos la hipótesis y nula y aceptamos la alterna evidenciando que la varianza de los errores no es constante.

Al tener en cuenta que solo uno de los modelos propuestos cumple con los supuestos del MRLM, y considerando los resulados de cada uno de los modelos, se procede a escoger el modelo No.1 como el más apropiados para realizar los siguientes procedimientos. Se decide escoger este modelo porque a pesar de que tiene un R cuadrado un poco inferior a los modelos 2 y 3, este si cumple con todos los supuestos del modelo.

Predicción de precios y potenciales ofertas.

Al finalizar con la modelación, se procede a realizar una predicción del precio de las vivienda y a responder el segundo interrogante requerido por la empresa a la compañia C&A.

vivienda_apartamentos_limpia$estrato <- as.numeric(as.character(vivienda_apartamentos_limpia$estrato))

requerimientos_apa <- data.frame(
estrato_numerico=c(5,6),
areaconst=c(300,300),
parqueaderos=c(3,3),
banios=c(3,3),
habitaciones=c(5,5),
preciom = c(0, 850)
)

requerimientos_apa
##   estrato_numerico areaconst parqueaderos banios habitaciones preciom
## 1                5       300            3      3            5       0
## 2                6       300            3      3            5     850
predicciones_apa <- predict(modelo_apartamentos, newdata = requerimientos_apa, interval = "confidence")

print(predicciones_apa)
##         fit      lwr       upr
## 1  952.7585 932.1671  973.3499
## 2 1011.6333 988.3326 1034.9340

Los anteriores resultados evidencian que considerando las condiciones establecidas, el precio medio de los aparatmentos están entre 952 y 1011 millones de pesos. Ahora procedemos a realizar el proceso de selección de los apartamentos.

Apartamento <- filter(vivienda_apartamentos_limpia, areaconst >= 300, parqueaderos >= 3, banios >= 3, habitaciones >= 4, zona == "Zona Sur", estrato >= 5, estrato <= 6, preciom <= 850)

min(Apartamento$preciom)
## [1] 670
max(Apartamento$preciom)
## [1] 730
cinco_aleatorios_apa <- Apartamento %>% sample_n(5, replace = TRUE)
print(cinco_aleatorios_apa)
## # A tibble: 5 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  7182 Zona S… <NA>        5     730       573            3      8            5
## 2  7512 Zona S… <NA>        5     670       300            3      5            6
## 3  7182 Zona S… <NA>        5     730       573            3      8            5
## 4  7182 Zona S… <NA>        5     730       573            3      8            5
## 5  7512 Zona S… <NA>        5     670       300            3      5            6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Con los datos anteriores, se obtienen los cincos datos requeridos para la organización y con los requerimientos necesarios.

cinco_aleatorios_apa <- Apartamento %>% sample_n(5, replace = TRUE)

mapaApartamentos <- leaflet(cinco_aleatorios_apa) %>%
  addTiles() %>%
   setView(lng =  -76.51595234451665, lat = 3.436834062816008, zoom = 12)  %>%
  addCircleMarkers(lng = cinco_aleatorios_apa$longitud,
                   lat = cinco_aleatorios_apa$latitud,
                   label = as.character(paste0(cinco_aleatorios_apa$tipo, " est:", cinco_aleatorios_apa$estrato, " Precio:",cinco_aleatorios_apa$preciom, "'000.000", " Pisos:", cinco_aleatorios_apa$piso, " Parqueaderos: ", cinco_aleatorios_apa$parqueaderos)), 
                   stroke = FALSE, 
                   fillOpacity = 0.5,
                   radius = 8,
                   color = "#228CF5"
                   )
mapaApartamentos

Con los datos anteriores, podemos ubicar en el mapa dos potenciales viviendas para dar respuesta a los requerimientos de la organización. Tal y como se establece en el mapa anterior y la tabla precedente se puede verificar que las dos viviendas identificas cumplen con los requerimientos de la empresa y de sus empleados para la adquisición de la misma.