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ñia C&A para responder a la solicitud
presentada por la empresa internacional.
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")
| 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")
| 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")
| 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")
| 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")
| 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.
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")
| 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")
| 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.
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.
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_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.
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.
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")
| 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")
| 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")
| 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")
| 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.
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")
| 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")
| 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.
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.
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_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.
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.