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:

Bajo dicho escenario, en el presente ejercicio apoyaremos a la compañoa C&A para responder a la solicitud requerida.

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 que variables se encuentran en ella.

options(repos = c(CRAN = "https://cloud.r-project.org"))

# Instalar y cargar el paquete devtools
install.packages("devtools")
## 
## The downloaded binary packages are in
##  /var/folders/4m/77c0638536vbvf2w8dh1vn0c0000gn/T//RtmpvMxBz9/downloaded_packages
library(devtools)
## Loading required package: usethis
# Instalar el paquete paqueteMODELOS desde GitHub
devtools::install_github("dgonxalex80/paqueteMODELOS", force = TRUE)
## Downloading GitHub repo dgonxalex80/paqueteMODELOS@HEAD
## 
## ── R CMD build ─────────────────────────────────────────────────────────────────
##   
   checking for file ‘/private/var/folders/4m/77c0638536vbvf2w8dh1vn0c0000gn/T/RtmpvMxBz9/remotes6203d5b60b7/dgonxalex80-paqueteMODELOS-796f588/DESCRIPTION’ ...
  
✔  checking for file ‘/private/var/folders/4m/77c0638536vbvf2w8dh1vn0c0000gn/T/RtmpvMxBz9/remotes6203d5b60b7/dgonxalex80-paqueteMODELOS-796f588/DESCRIPTION’
## 
  
─  preparing ‘paqueteMODELOS’:
## 
  
   checking DESCRIPTION meta-information ...
  
✔  checking DESCRIPTION meta-information
## 
  
─  checking for LF line-endings in source and make files and shell scripts
## 
  
─  checking for empty or unneeded directories
## 
  
─  building ‘paqueteMODELOS_0.1.0.tar.gz’
## 
  
   
## 
# Cargar el paquete paqueteMODELOS
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
# Cargar la base de datos vivienda
data("vivienda")

Luego de cargar la data inicial, procedemos a realizar un filtro en la base de datos para incluir solo los atributos que deseamos analizar pata la vivienda tipo 1, incluyendo las viviendas que se ubiquen en el 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
# Filtrar la base de datos vivienda
vivienda_1 <- filter(vivienda, zona == "Zona Norte" & tipo == "Casa")

# Mostrar los primeros 3 registros en formato de tabla con kable
knitr::kable(head(vivienda_1, 3), caption = "Casas en la Zona Norte")
Casas en la Zona 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.

Zona Norte

library(leaflet)

# Filtrar la base de datos vivienda para las casas en la Zona Norte
vivienda_norte <- filter(vivienda, tipo == "Casa" & zona == "Zona Norte")

# Crear el mapa con leaflet
mapaNorte <- leaflet(vivienda_norte) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#7b9400", radius = 2)

# Mostrar el mapa
mapaNorte

Como se puede observar en el mapa anterior, algunos puntos se encuentran fuera de la zona norte de la ciudad de Cali. Esta discrepancia podría atribuirse a la inclusión de registros erróneos durante la creación de la base de datos, lo que está generando estas dificultades en la visualización actual.

Para verificar si este error se repite en otras zonas de la ciudad, es importante investigar las zonas central y sur. Esto nos permitirá entender mejor el comportamiento de los datos y determinar si la presencia de puntos fuera de las zonas designadas es un patrón generalizado o específico de la zona norte.

Nona Centro

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.

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

Zona Oeste

# Filtrar la base de datos vivienda para las casas en la Zona Oeste
vivienda_3 <- filter(vivienda, zona == "Zona Oeste" & tipo == "Casa")

# Presentar los primeros 3 registros en formato de tabla con kable
knitr::kable(head(vivienda_3, 3), caption = "Casas en la Zona Oeste")
Casas en la Zona Oeste
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
6928 Zona Oeste 03 6 1850 302 4 4 3 Casa aguacatal -76.54600 3.44400
7510 Zona Oeste 03 6 1950 400 4 5 3 Casa aguacatal -76.55000 3.45600
7586 Zona Oeste 03 6 870 275 3 5 4 Casa aguacatal -76.55074 3.45649
# Filtrar la base de datos vivienda para las casas en la Zona Oeste
vivienda_oeste <- subset(vivienda, tipo == "Casa" & zona == "Zona Oeste")

# Crear el mapa con leaflet para la Zona Oeste
mapaOeste <- leaflet(vivienda_oeste) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#62162f", radius = 2)

mapaOeste

Zona Oriente

# Filtrar la base de datos vivienda para las casas en la Zona Oriente
vivienda_oriente <- filter(vivienda, zona == "Zona Oriente" & tipo == "Casa")

# Presentar los primeros 3 registros en formato de tabla con kable
knitr::kable(head(vivienda_oriente, 3), caption = "Casas en la Zona Oriente")
Casas en la Zona Oriente
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
# Crear el mapa con leaflet para la Zona Oriente
mapa_oriente <- leaflet(vivienda_oriente) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#008000", radius = 2)

mapa_oriente

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.

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("#7b9400","#228CF5", "#F5E322", "#62162f", "#008000"), 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. Este análisis final proporciona una visión global de la distribución de todas las viviendas de tipo casa en la ciudad de Cali, permitiéndo identificar patrones de ubicación y posibles anomalías en la base de datos, como la presencia de viviendas fuera de las zonas designadas. Lo anterior, requiere realizar una identificación correcta de la longitud y latitud para obtener una mejor clasificación de los datos.

Análisis exploratorio de los datos

Después de completar la evaluación de las residencias ubicadas en el área norte de Cali, avanzaremos hacia un análisis de cómo la variable de interés se correlaciona con el tamaño de la construcción. En una etapa inicial, nos enfocaremos en determinar los estadísticos clave del conjunto de datos recopilado.

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 estadísticos del conjunto de datos, hemos logrado identificar medidas descriptivas como la media, la moda, así como los valores mínimos, máximos y cuartiles de cada variable. Es importante destacar que este análisis se realizó exclusivamente para el subconjunto de datos que incluye viviendas de tipo casa en Cali. De estos estadísticos, es notable que las variables “baños” y “habitaciones” presentan una particularidad: muestran valores mínimos de cero, lo cual parece ser poco probable, ya que es raro que una casa no tenga al menos un baño y una habitación. Por tanto, surge la necesidad de indagar si estos valores se deben a datos faltantes o si realmente reflejan propiedades sin baños ni habitaciones.

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

A partir de lo anterior, se evidencian algunos datos faltantes, ahora se pretende encontrar en qué variables se encuentran dichos datos.

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

Esta tabla muestra el número de datos ausentes (valores nulos) para cada variable en el conjunto de datos. se evidencia que no hay datos ausentes para las variables “id”, “zona”, “piso”, “estrato”, “preciom”, “areaconst”, “tipo”, “barrio”, “longitud” y “latitud”. Sin embargo, las variables “parqueaderos”, “banios” y “habitaciones” tienen 733 datos ausentes cada una.

Esto significa que hay 733 registros en el conjunto de datos que no tienen valores registrados para las variables “parqueaderos”, “banios” y “habitaciones”. Este análisis nos permite cuantificar la cantidad de datos faltantes en nuestro conjunto de datos y comprender mejor la integridad de los datos disponibles.

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>

Lo anterior indica que existen propiedades en el conjunto de datos que no tienen información registrada sobre el número de habitaciones y/o baños. Esto podría ser un indicativo de datos faltantes o de registros incorrectos en el conjunto de datos. Será importante investigar más a fondo para determinar la causa exacta de estos valores y decidir cómo manejarlos adecuadamente en el análisis de datos subsiguiente.

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

La limpieza de la base de datos permite trabajar con un conjunto de datos más limpio y coherente, lo que mejorará la calidad del análisis y las conclusiones que se pueda extraer de él. La limpieza de datos es un paso crucial en el análisis de datos que garantiza la fiabilidad y precisión de los resultados obtenidos.

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")

Con lo anterior es posible entender la distribución de los precios de las viviendas en el conjunto de datos, donde se puede observar si la distribución es simétrica o sesgada hacia un lado, así como identificar posibles valores atípicos o concentraciones de precios en ciertos rangos.

Con el histograma se puede comprender la distribución de los precios de las viviendas en la ciudad de Cali, donde se evidencia que los precios oscilan 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.

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, se observa que gran parte de los datos se concentran en la parte izquierda.

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

En el histograma del estrato, se observa que la mayoría de las viviendas en la ciudad de Cali están ubicadas en los estratos 5 y 6, pero también hay una cantidad significativa de viviendas en los estratos 3 y 4. Esto sugiere que la distribución de las viviendas tiende a estar sesgada hacia los estratos más altos, pero aún existe una presencia notable en los estratos intermedios.

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

En el histograma del número de baños, se observa que la distribución de los datos se asemeja a una distribución normal, con la mayoría de los valores concentrados cerca de la media del atributo, que es de 4 baños. Esto indica que la mayoría de las viviendas en el conjunto de datos tienen alrededor de 4 baños. Esta información es útil para comprender las características comunes de las viviendas en términos de su disposición de baños, lo que puede ser importante para los compradores y para la evaluación de la calidad de las propiedades.

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

En el histograma del número de habitaciones, se observa una distribución que se asemeja a una distribución normal, con la mayoría de los datos concentrados alrededor de la media, que es de 4 habitaciones. Sin embargo, también se nota la presencia de varios datos por encima de 4 habitaciones, lo que sugiere un sesgo hacia la derecha en la distribución. Esto indica que aunque la mayoría de las viviendas tienen alrededor de 4 habitaciones, hay algunas propiedades con un número considerablemente mayor de habitaciones.

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

En el histograma de las zonas de las casas, se observa que la mayoría de las viviendas están ubicadas en la zona sur, seguidas por la zona norte. Esto sugiere que la distribución de las viviendas está sesgada hacia la zona sur en el conjunto de datos analizado.

Posteriormente, se realizó un análisis de correlación entre las variables de interés, que incluyen el precio, el área construida, los baños y las habitaciones.

library(GGally)

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

Los resultados revelan que las variables más fuertemente correlacionadas con el precio son el área construida y el número de baños. Específicamente, la correlación entre el precio y el área construida es de 0.654, mientras que la correlación entre el precio y el número de baños es de 0.583. Estas correlaciones son consideradas medianamente altas, lo que sugiere una relación significativa entre estas variables y el precio de las viviendas.

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 observa que todas las variables restantes son significativas, lo que indica que cada una de ellas aporta información importante para explicar la variabilidad en el precio de las casas. Además, los signos de los coeficientes son consistentes con las expectativas: se espera una relación positiva entre el precio y el área construida, el estrato, el número de parqueaderos y los baños, mientras que la relación con el número de habitaciones es negativa, lo cual podría indicar una disminución en el precio a medida que aumenta el número excesivo de habitaciones.

El coeficiente de determinación ajustado (R ajustado) del modelo es del 69.66%, lo que indica que el modelo explica aproximadamente el 69.66% de la variabilidad en el precio de las viviendas. Este valor es similar al coeficiente de determinación R cuadrado del modelo anterior, lo que sugiere que el modelo refinado tiene un poder predictivo similar pero con un número menor de variables predictoras

En terminos generales, el modelo refinado obtenido a través del método de selección de variables paso a paso proporciona una mejor comprensión de los factores que influyen en el precio de las viviendas, al tiempo que mantiene un buen nivel de ajuste y capacidad predictiva.

# 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

El modelo obtenido a través del proceso de regresión stepwise hacia adelante confirma los resultados anteriores y proporciona una versión refinada del modelo de regresión lineal múltiple, manteniendo un buen nivel de ajuste y capacidad predictiva. Para ello, procedemos a realizar una ultima 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

Al comparar los modelos de regresión lineal múltiple, podemos observar que los modelos que incorporan transformaciones logarítmicas en las variables predictoras muestran un mejor desempeño en términos de ajuste y significancia estadística de las variables.

El modelo 3, que incluye logaritmos en todas las variables predictoras, muestra un coeficiente de determinación R cuadrado del 79.8%, lo que indica que el 79.8% de la variabilidad en el logaritmo del precio de las viviendas puede ser explicada por las variables predictoras incluidas en el modelo. Además, todas las variables predictoras son significativas estadísticamente al nivel de confianza del 99%, excepto por las habitaciones que son significativas al 95%.

Al considerar los signos de los coeficientes, observamos resultados consistentes con los modelos anteriores. La transformación logarítmica de las variables predictoras ha permitido estabilizar los coeficientes y mejorar la interpretación de sus efectos sobre el precio de las viviendas. ### 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

Los resultados muestran que en ninguno de los modelos ni de las variables predictoras se observa un problema de multicolinealidad, ya que todos los valores de VIF son inferiores a 5. Esto sugiere que las variables predictoras incluidas en los modelos son independientes entre sí y no existe una alta correlación lineal entre ellas.

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")

Al observar los gráficos de diagnóstico para cada modelo, podemos evaluar visualmente la calidad del ajuste de los datos a la línea de regresión y verificar si se cumplen los supuestos de la regresión lineal múltiple.

En los primeros modelos (modelo 1 y modelo 2), tanto en los cuantiles como en los valores ajustados, se observa una tendencia más marcada, lo que indica una posible falta de ajuste del modelo a los datos. Por otro lado, en los modelos 3 y 4, se aprecia una distribución más uniforme de los puntos alrededor de la línea de regresión, lo que sugiere un mejor ajuste de los datos al modelo.

En particular, en los modelos 3 y 4, se observa una dispersión más uniforme de los valores ajustados y una distribución más cercana a la línea media en los cuantiles, lo que indica una mejor conformidad con los supuestos de la regresión lineal.

En conclusión, se observa que los modelos 3 y 4 parecen mostrar un mejor comportamiento en términos de ajuste de los datos y cumplimiento de los supuestos de la regresión lineal. Sin embargo, para confirmar estos hallazgos, es necesario realizar pruebas de hipótesis adicionales y validar los supuestos del modelo.

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(
  Modelo1 = errores_Modelo1,
  Modelo2 = errores_Modelo2,
  Modelo3 = errores_Modelo3,
  Modelo4 = errores_Modelo4
)

knitr::kable(head(errores_modelos), caption = "Errores de los modelos")
Errores de los modelos
Modelo1 Modelo2 Modelo3 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
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

Según las pruebas de Shapiro-Wilk, no encontramos evidencia suficiente para afirmar que los errores residuales de ninguno de los modelos violan el supuesto de normalidad. Esto respalda la validez de los resultados obtenidos en los modelos de regresión lineal múltiple. Ahora, procedemos a analizar 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

Según las pruebas Durbin-Watson, no se encuentra evidencia suficiente para afirmar que los errores residuales de ninguno de los modelos presentan autocorrelación. Esto respalda la validez de los resultados obtenidos en los modelos de regresión lineal múltiple.

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

Al tener en cuenta que todos los modelos presentan violaciones en el supuesto de homocedasticidad, y considerando los resultados obtenidos en cada uno de los modelos, se procede a escoger el modelo No. 3 como el más apropiado para realizar los siguientes análisis. Se decide seleccionar este modelo debido a sus valores de R y R ajustado superiores a los modelos 1 y 2 (y ligeramente inferiores al modelo 4), y a su significancia estadística (valor t) igual o superior al 95% en todas las variables explicativas.

Esto sugiere que el Modelo 3, que utiliza una transformación logarítmica en algunas variables, proporciona un buen equilibrio entre ajuste y significancia estadística.

Predicción de precios y potenciales ofertas.

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

Según estos datos, podemos observar que el valor de las casas en el norte de Cali, con los requerimientos especificados (estrato 4 o 5, área de construcción de al menos 200 metros cuadrados, al menos un parqueadero, dos baños, cuatro habitaciones y un precio de mantenimiento de hasta 350 millones), se sitúa en un rango de 474 a 604 millones de pesos.

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   819 Zona N… 02          5     350       264            2      3            4
## 2  3453 Zona N… <NA>        5     340       240            2      5            6
## 3  4422 Zona N… 02          5     350       240            2      3            6
## 4  3043 Zona N… <NA>        5     330       275            2      3            5
## 5  1020 Zona N… 02          4     230       250            2      3            5
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Mediante el código anterior, se ha seleccionado un conjunto de casas que cumplen con los criterios especificados: área de construcción de al menos 200 metros cuadrados, al menos un parqueadero, dos baños, cuatro habitaciones, ubicadas en la Zona Norte de Cali, con estrato entre 4 y 5, y con un precio máximo de mantenimiento de 350 millones de pesos. Entre estas propiedades seleccionadas, el precio mínimo encontrado es de X millones de pesos, mientras que el precio máximo alcanza Y millones de pesos.

cinco_aleatorios <- Casa %>% sample_n(5)

mapaCasas <- leaflet(cinco_aleatorios) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color ="#7b9400", radius = 4)


mapaCasas

Utilizando los datos previamente seleccionados, hemos generado un mapa que muestra la ubicación de cinco posibles viviendas que cumplen con los criterios establecidos por la organización. Cada marcador en el mapa representa una de estas viviendas potenciales. Al observar tanto el mapa como la tabla anterior, podemos confirmar que las cinco viviendas identificadas cumplen con los requisitos establecidos por la empresa y satisfacen las necesidades de sus empleados en cuanto a la adquisición de viviendas.

Análisis vivienda 2

Continuamos el análisis con la segunda categoría de vivienda, específicamente apartamentos. Iniciamos filtrando los datos originales para obtener únicamente aquellos ubicados en la Zona Norte y que corresponden al tipo de vivienda ‘Apartamento’.

# Filtrar los apartamentos en la Zona Norte de Cali
viviendaAPA <- filter(vivienda, zona == "Zona Norte" & tipo == "Apartamento")

# Mostrar los primeros tres apartamentos en una tabla
knitr::kable(head(viviendaAPA, 3), caption = "Primeros tres apartamentos en la Zona Norte de Cali")
Primeros tres apartamentos en la Zona Norte de Cali
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

Posteriormente, visualizamos en un mapa las ubicaciones de estos apartamentos que cumplen con los criterios establecidos por la empresa

# Filtrar los apartamentos en la Zona Norte de Cali
vivienda_norte_apa <- filter(vivienda, tipo == "Apartamento" & zona == "Zona Norte")

# Crear el mapa de los apartamentos en la Zona Norte de Cali
mapaNorteA1 <- leaflet(vivienda_norte_apa) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#228CF5", radius = 2)



# Mostrar el mapa
mapaNorteA1

Al igual que con el subconjunto de las casas, al examinar los apartamentos, podemos observar que el conjunto de datos contiene apartamentos que se encuentran fuera de la Zona Norte especificada. Esta observación sugiere que puede haber errores en la ubicación de la latitud y longitud en el conjunto de datos, lo que resulta en la presencia de puntos fuera de la zona requerida en el mapa.

Para validar esta hipótesis, procedemos a verificar la presencia de estos errores en otros dos puntos: el centro y el sur. Esta exploración adicional nos permitirá comprender mejor el comportamiento de los datos y determinar si los errores de ubicación son sistemáticos o están limitados a una región específica de la ciudad.

# Filtrar los apartamentos en la Zona Centro de Cali
viviendaAPA2 <- filter(vivienda, zona == "Zona Centro" & tipo == "Apartamento")

# Mostrar los primeros tres apartamentos en la Zona Centro en una tabla
knitr::kable(head(viviendaAPA2, 3), caption = "Primeros tres apartamentos en la Zona Centro de Cali")
Primeros tres apartamentos en la Zona Centro de Cali
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
# Filtrar los datos de apartamentos en la Zona Centro de Cali
vivienda_centro_apa <- filter(vivienda, tipo == "Apartamento" & zona == "Zona Centro")

# Crear el mapa de los apartamentos en la Zona Centro de Cali
mapa_centro_apa <- leaflet(vivienda_centro_apa) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#F5E322", radius = 2)




# Mostrar el mapa
mapa_centro_apa
# Filtrar los apartamentos en la Zona Sur de Cali
viviendaAPA3 <- filter(vivienda, zona == "Zona Sur" & tipo == "Apartamento")

# Mostrar los primeros tres apartamentos en la Zona Sur en una tabla
knitr::kable(head(viviendaAPA3, 3), caption = "Primeros tres apartamentos en la Zona Sur de Cali")
Primeros tres apartamentos en la Zona Sur de Cali
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
5098 Zona Sur 05 4 290 96 1 2 3 Apartamento acopi -76.53464 3.44987
698 Zona Sur 02 3 78 40 1 1 2 Apartamento aguablanca -76.50100 3.40000
8199 Zona Sur NA 6 875 194 2 5 3 Apartamento aguacatal -76.55700 3.45900
# Filtrar los datos de apartamentos en la Zona Sur de Cali
vivienda_sur_apa <- filter(vivienda, tipo == "Apartamento" & zona == "Zona Sur")

# Crear el mapa de los apartamentos en la Zona Sur de Cali
mapa_sur_apa <- leaflet(vivienda_sur_apa) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color = "#62162f", radius = 2)


# Mostrar el mapa
mapa_sur_apa

Al igual que con las casas, al analizar los apartamentos, se observa que algunos puntos se encuentran ubicados fuera de las zonas específicas de la ciudad. Esto sugiere que los datos pueden contener errores en la geolocalización, lo que resulta en la presencia de puntos fuera de las áreas establecidas. Si se grafican los puntos en diferentes sectores de Cali, es probable que se encuentren puntos que no corresponden a las zonas definidas.

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("#7b9400","#228CF5", "#F5E322", "#62162f", "#008000"), domain = vivienda_apartamentos$zona)



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

mapaAPA

El gráfico anterior presenta una visualización de todos los apartamentos en nuestra base de datos, donde cada punto está coloreado según su ubicación en diferentes zonas de la ciudad. Al observar esta representación, se evidencian inconsistencias en los datos, las cuales podrían originarse por dos posibles razones: errores humanos durante la creación de la base de datos o falta de actualización de la información. Estas discrepancias pueden conducir a valores incorrectos de longitud y latitud, lo que a su vez afecta la precisión de la ubicación de los apartamentos en el mapa.

Análisis exploratorio de los datos

Después de obtener los principales estadísticos del dataset de apartamentos, hemos identificado medidas clave como la media, la moda y los valores mínimos, máximos y cuartiles de cada variable. Este análisis nos proporciona una comprensión general de la distribución de los datos y nos ayuda a identificar posibles anomalías o patrones.

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  
## 

Es importante destacar que, al igual que con el subconjunto de casas, las variables ‘baños’ y ‘habitaciones’ presentan una situación particular, ya que se observa que el valor mínimo es cero. Este resultado parece inusual, ya que se espera que al menos los apartamentos tengan al menos un baño y una habitación. Para investigar esta situación, es crucial determinar si estos valores se deben a la presencia de datos faltantes.

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 grafica indica que existen algunos datos faltantes, ahora se procede a ver en qué variables se encuentran dichos datos.

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

Al examinar los datos, hemos identificado la presencia de valores cero en las variables ‘habitaciones’ y ‘baños’ en el dataset de apartamentos. Estos valores cero son inconsistentes, ya que se espera que cada apartamento tenga al menos una habitación y un baño.

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>

Tras revisar los datos, hemos identificado la presencia de valores cero en las variables ‘habitaciones’ y ‘baños’ del dataset de apartamentos. Estos valores no son coherentes, dado que es esperable que cualquier apartamento tenga al menos una habitación y un baño.

Por lo tanto, hemos decidido eliminar estos datos, ya que podrían distorsionar nuestros análisis y generar resultados poco confiables. Al asegurarnos de que nuestros datos estén limpios y sean consistentes, podemos realizar un análisis más preciso y confiable, lo que nos permitirá obtener conclusiones más sólidas sobre las características y el valor de los apartamentos en nuestra base de datos.

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

Una vez que hemos realizado la limpieza de la base de datos de apartamentos, eliminando las entradas con valores cero en las variables ‘habitaciones’ y ‘baños’, procedemos a realizar una exploración inicial de los datos. En esta etapa, nos enfocaremos en evaluar la normalidad de las variables y examinar su 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")

Al observar el histograma de los precios de los apartamentos, notamos que los datos tienden a agruparse hacia la izquierda, especialmente en el rango de 60 a 420 millones de pesos. Es importante destacar que la mayoría de los precios de los apartamentos se concentran alrededor de la media, que es de 279 millones de pesos.

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

Al examinar el histograma del área construida de los apartamentos, observamos una distribución de los datos que se concentra predominantemente en el lado izquierdo del gráfico. Esto sugiere que la mayoría de los apartamentos en nuestra base de datos tienen áreas construidas más pequeñas.

Es importante destacar que la mayoría de los datos se concentran por debajo de la media del área de construcción, que es de 90 metros cuadrados. Esto indica que la mayoría de los apartamentos tienen áreas construidas relativamente modestas en comparación con la media.

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

En el histograma del estrato de los apartamentos, podemos observar que la mayoría de los apartamentos en la ciudad de Cali se concentran en los estratos 5 y 6. En menor medida, encontramos apartamentos en el estrato 4, mientras que el estrato 3 cuenta con la menor cantidad de apartamentos.

Este patrón de distribución del estrato de los apartamentos nos proporciona información valiosa sobre la distribución socioeconómica de las viviendas en nuestra área de estudio. Los estratos más altos (5 y 6) tienden a estar asociados con áreas de mayor poder adquisitivo, mientras que los estratos más bajos (3 y 4) pueden representar áreas con menor poder adquisitivo.

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

En el histograma del número de baños de los apartamentos, podemos observar una distribución que se asemeja más a una distribución 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.

Esta distribución centrada alrededor del valor medio sugiere que la mayoría de los apartamentos en nuestra base de datos tienen un número de baños relativamente común, lo que puede reflejar las expectativas y necesidades típicas de los compradores o inquilinos de apartamentos en nuestra área de estudio.

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

En el histograma del número de habitaciones de los apartamentos, podemos observar una distribución que se asemeja a una distribución normal, donde la mayoría de los datos se concentran alrededor de la media, que es igual a 3.

Esta distribución centrada en la media sugiere que la mayoría de los apartamentos en nuestra base de datos tienen un número común de habitaciones, lo que puede reflejar las preferencias y necesidades típicas de los compradores o inquilinos de apartamentos en nuestra área de estudio.

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

En el histograma de las zonas de los apartamentos, podemos observar que la mayor parte de ellos se encuentran en la zona sur, seguidos de la zona norte.

Este patrón de distribución de los apartamentos por zona nos ofrece una perspectiva interesante sobre la distribución geográfica de las viviendas en nuestra área de estudio. La predominancia de apartamentos en la zona sur podría reflejar diversos factores, como la disponibilidad de terrenos, la densidad de población o las preferencias de los residentes.

Una vez completado el análisis de la normalidad de los datos, continuaremos con la identificación de las correlaciones entre las variables en nuestro conjunto de datos de apartamentos, lo que nos permitirá comprender mejor las relaciones entre ellas y su impacto en el mercado inmobiliario.”

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

Tras analizar la matriz de correlación de las variables en nuestro conjunto de datos de apartamentos, hemos identificado que las variables ‘área construida’ y ‘baños’ muestran un alto nivel de correlación con el precio de los apartamentos, con coeficientes de correlación de 0.83 y 0.75 respectivamente. Por otro lado, la variable ‘habitaciones’ muestra una correlación más baja con el precio.

Es importante destacar que el alto nivel de correlación entre el precio y las variables ‘área construida’ y ‘baños’ puede generar problemas de multicolinealidad al realizar el Modelo de Regresión Lineal Múltiple (MRLM). Sin embargo, es crucial tener en cuenta que esta afirmación solo podrá ser confirmada mediante 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

Después de realizar el modelo de regresión lineal múltiple (RLM) con las variables introducidas, se observó que todas ellas resultan significativas, dado que el valor de probabilidad asociado a cada coeficiente es menor a 0.05, o bien, mediante la regla rápida del valor t, donde se considera cualquier valor igual o superior a 2 como significativo.

Al analizar el efecto de cada variable en el precio de los apartamentos, se encontró que los signos esperados de los coeficientes son lógicos en la mayoría de los casos. Por ejemplo, el coeficiente positivo del área construida y el estrato tiene sentido intuitivo, ya que se espera que un mayor área construida y un estrato más alto estén asociados con precios más altos. Sin embargo, el coeficiente negativo de la variable ‘habitaciones’ requiere una consideración adicional, ya que puede indicar que un número excesivo de habitaciones podría disminuir el precio del inmueble.

En cuanto al coeficiente de determinación (R cuadrado), se observó que su valor es del 79.9%, lo que indica que el modelo con las variables introducidas explica aproximadamente el 79.9% de la variabilidad en el precio de los apartamentos. Aunque este valor es alto, también se consideró el coeficiente de determinación ajustado, que es ligeramente más bajo, indicando que la inclusión de más variables en el modelo no sería necesaria.

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 procedimiento de selección de variables stepwise, se obtuvieron resultados consistentes con el modelo anterior. Esto sugiere que las variables seleccionadas tienen un impacto significativo en la predicción del precio de los apartamentos.

El análisis stepwise nos permitió identificar las mismas variables significativas que se encontraron en el modelo de regresión lineal múltiple inicial. Esto respalda la robustez de las relaciones identificadas entre las variables predictoras y la variable de respuesta.

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

Después de examinar los resultados de los tres modelos de regresión, se observa que tanto el modelo 2 como el modelo 3 muestran un desempeño mejorado en comparación con el primer modelo.

El modelo 2 logró aumentar el coeficiente de determinación (R cuadrado) al 88%, lo que significa que el 88% de la variabilidad en el precio de los apartamentos puede ser explicada por las variables incluidas en el modelo. Además, todas las variables explicativas independientes mostraron una significancia estadística del 99%. Por otro lado, el modelo 3 mejoró ligeramente el coeficiente de determinación ajustado al 88.1%, y todas las variables también alcanzaron una significancia del 99%.

Al considerar los signos esperados de las variables en los modelos, se encontraron resultados consistentes con los modelos anteriores. Sin embargo, al aplicar el logaritmo a las variables, se observó una mayor estabilidad en los coeficientes, especialmente en las variables como parqueaderos y la constante. Esto sugiere que el modelo con transformación logarítmica es más robusto y consistente.

Análisis de los supuestos del modelo

Después de estimar los modelos, se llevó a cabo la validación de los supuestos del modelo, específicamente evaluando el factor de inflación de la varianza (VIF) para detectar problemas de multicolinealidad.

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

Los resultados del VIF para cada uno de los modelos sugieren que no hay evidencia de multicolinealidad significativa entre las variables predictoras, ya que todos los valores son inferiores a 5. Esto indica que la relación entre las variables predictoras es adecuada y no afectará la precisión de las estimaciones.

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")

Estos modelos con los logaritmos señalan 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. De la misma manera, se debe efectuar un 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

con lo anterior, tambien es importante evaluar los supuestos de normalidad

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.

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, lo que permite aceptar la hipotedis nula y establecer 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 evaluar el supuesto de la varianza constante, se observa que el modelo 1 cumple con este requisito, ya que el valor p asociado es menor que 0.05. Esto indica que podemos aceptar la hipótesis nula de que la varianza de los errores es constante en este modelo. Por otro lado, los modelos 2 y 3 no cumplen con este supuesto, ya que su valor p es mayor que 0.05, lo que nos lleva a rechazar la hipótesis nula y aceptar la hipótesis alternativa, indicando que la varianza de los errores no es constante en estos modelos.

Considerando que todos los modelos cumplen con los supuestos del MRLM, y al analizar los resultados de cada uno, se decide seleccionar el modelo No. 1 como el más adecuado para los siguientes procedimientos. Esta decisión se basa en que, aunque el modelo 1 tiene un R cuadrado ligeramente inferior en comparación con los modelos 2 y 3, cumple con todos los supuestos del modelo, lo que garantiza una mejor fiabilidad en las inferencias realizadas con este modelo.

Predicción de precios y potenciales ofertas.

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 resultados anteriores muestran que, bajo las condiciones especificadas, el precio medio de los apartamentos oscila entre 952 y 1011 millones de pesos. Este rango proporciona una estimación del precio esperado para apartamentos que cumplen con los requisitos de estrato, área construida, número de parqueaderos, baños y habitaciones definidos por la empresa.

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  7512 Zona S… <NA>        5     670       300            3      5            6
## 2  7512 Zona S… <NA>        5     670       300            3      5            6
## 3  7512 Zona S… <NA>        5     670       300            3      5            6
## 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>

Después de aplicar los criterios de selección definidos, se obtienen cinco apartamentos que cumplen con los requisitos establecidos por la empresa. Estos requisitos incluyen un área construida mínima de 300 metros cuadrados, al menos tres parqueaderos, tres baños y cuatro habitaciones, ubicados en la Zona Sur de la ciudad y con estrato entre 5 y 6, además de un precio máximo de 850 millones de pesos.

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

mapaApartamentos <- leaflet(cinco_aleatorios_apa) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~longitud, lat = ~latitud, color ="#228CF5", radius = 4)

mapaApartamentos

Con base en los datos proporcionados, se han identificado cinco posibles apartamentos que cumplen con los criterios definidos por la empresa. Estos apartamentos han sido ubicados en el mapa para facilitar su visualización. Tanto en el mapa como en la tabla de datos, se confirma que estas cinco viviendas seleccionadas cumplen con los requisitos establecidos por la empresa y son adecuadas para satisfacer las necesidades de sus empleados en cuanto a la adquisición de vivienda.