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:
| Características | Vivienda 1 | Vivienda 2 |
|---|---|---|
| Tipo | Casa | Apartamento |
| Área Construida | 200 | 300 |
| parqueaderos | 1 | 3 |
| baños | 2 | 3 |
| habitaciones | 4 | 5 |
| estrato | 4 o 5 | 5 o 6 |
| Zona | Norte | Sur |
| Crédito preaprobado | 350 millones | 850 millones |
# devtools::install_github("dgonxalex80/paqueteMODELOS", force =TRUE)
library(paqueteMODELOS)
data("vivienda")
(Adicional un mapa con los puntos de las bases. Discutir si todos los puntos se ubican en la zona correspondiente o se presentan valores en otras zonas, por que?).
En primer lugar, se genera una pequeña tabla de contingencia sobre la base de datos general, con el objetivo de verificar la totalidad de tipo de vivienda, sean apartamentos o casas, respecto a la zona revelada en la base de datos:
table(vivienda$zona,vivienda$tipo)
##
## Apartamento Casa
## Zona Centro 24 100
## Zona Norte 1198 722
## Zona Oeste 1029 169
## Zona Oriente 62 289
## Zona Sur 2787 1939
Existen un total de 722 registros para casas en zona norte, lo que se validará al momento de generar la consulta. Se procede a efectuar el filtrado de la base de datos por los atributos solicitados, junto con los tres primeros registros de la consulta:
library(dplyr)
vivienda_casas <- filter(vivienda, zona == "Zona Norte" & tipo =="Casa")
head(vivienda_casas, 3)
| 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 |
Los tres primeros registros corresponden a los id 1209, 1592 y 4057. El barrio de las tres casas es “Acopi”, que de acuerdo con lo investigado, es un sector de la zona norte, comuna 2, que aunque no salga listado como barrio, está conurbano con la zona del mismo nombre con el municipio de Yumbo al norte, por lo que se concluye por el momento que los datos son consistentes
table(vivienda_casas$zona,vivienda_casas$tipo)
##
## Casa
## Zona Norte 722
En efecto, se concluye que la base de datos filtrada tiene 722 registros, todos correspondientes a los atributos “casa” en “zona norte”. Se efectúa una última validación :
glimpse(vivienda_casas)
## Rows: 722
## Columns: 13
## $ id <dbl> 1209, 1592, 4057, 4460, 6081, 7824, 7987, 3495, 141, 243,…
## $ zona <chr> "Zona Norte", "Zona Norte", "Zona Norte", "Zona Norte", "…
## $ piso <chr> "02", "02", "02", "02", "02", "02", "02", "03", NA, NA, N…
## $ estrato <dbl> 5, 5, 6, 4, 5, 4, 5, 5, 3, 3, 3, 3, 5, 3, 4, 4, 5, 5, 4, …
## $ preciom <dbl> 320, 780, 750, 625, 750, 600, 420, 490, 230, 190, 180, 50…
## $ areaconst <dbl> 150, 380, 445, 355, 237, 160, 200, 118, 160, 435, 120, 21…
## $ parqueaderos <dbl> 2, 2, NA, 3, 2, 1, 4, 2, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ banios <dbl> 4, 3, 7, 5, 6, 4, 4, 4, 2, 0, 3, 6, 5, 5, 3, 3, 4, 5, 5, …
## $ habitaciones <dbl> 6, 3, 6, 5, 6, 5, 5, 4, 3, 0, 3, 6, 4, 8, 4, 3, 4, 6, 4, …
## $ tipo <chr> "Casa", "Casa", "Casa", "Casa", "Casa", "Casa", "Casa", "…
## $ barrio <chr> "acopi", "acopi", "acopi", "acopi", "acopi", "acopi", "ac…
## $ longitud <dbl> -76.51341, -76.51674, -76.52950, -76.53179, -76.54044, -7…
## $ latitud <dbl> 3.47968, 3.48721, 3.38527, 3.40590, 3.36862, 3.42125, 3.4…
Con lo anterior, se confirma que los registros de la base de datos quedaron correctamente filtrados. Ahora bien, se valida si efectivamente todos los 722 registros quedaron ubicados en la zona norte. Para lo anterior, debemos definir qué es la zona norte de la ciudad de cali, para lo que se acude a la información contenida en la Alcaldía de Cali, portal de Infraestructura de Datos Espaciales de Santiago de Cali - IDESC
La primera referencia para definir la zona norte es la siguiente:
” Zona Norte: Para su definición, se tuvieron en cuenta aspectos como los sectores de las calles y carreras norte establecidos en la guía para la nomenclatura urbana de Santiago de Cali, pero también aquellos barrios y sectores que la comunidad reconoce como norte de la ciudad. Esta zona comprende el territorio que va desde la KR 1 entre la CL 1 OESTE hasta el separador vial ubicado entre las CL 25 y CL 26, vía por la cual se continúa hasta la KR 7, y desde este punto, siguiendo el trazado del corredor férreo hasta llegar a la CL 88, a partir de la cual, se continua hacia el norte por el límite del suelo urbano hasta finalizar en el punto de inicio en la KR 1. ” Tomado de: https://www.cali.gov.co/planeacion/publicaciones/169423/zonas_geograficas_idesc/
Ahora bien, se construye un polígono con las comunas 2, 4, 5, y 6, disponibles como geodatabase con la información disponible en la siguiente página: https://www.cali.gov.co/planeacion/publicaciones/172941/datos_divipola_idesc/
Esto se almacena en archivo .shp, generado con Argis, previamente aplicando Dissolve (para que fuese un sólo polígono) y transformando el sistema de coordenadas planas a WGS 84.
Para el propósito, cargamos la libreríua leaflet y sf (para leer la capa), y se efectúa la visualización solicitada:
library(leaflet)
library(sf)
# Primer Mapa
zona_norte <- read_sf("C:/Users/lidersui/OneDrive - URBASER/Escritorio/divipola/ZONA_NORTE_POLIGONO_wgs.shp")
mapa1 <- leaflet(vivienda_casas) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = zona_norte, color = "red", stroke = 1, opacity = 0.5) %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste0("<b>Id: </b>",id , "<br>",
"<b>Zona: </b>",zona, "<br>",
"<b>Tipo: </b>",tipo, "<br>",
"<b>Barrio: </b>",barrio, "<br>",
"<b>Estrato: </b>",estrato, "<br>",
"<b>Precio(mill): </b>",preciom, "<br>",
"<b>Habitaciones: </b>",habitaciones, "<br>",
"<b>Banios: </b>",banios, "<br>",
"<b>Parqueaderos: </b>",parqueaderos, "<br>")
)
mapa1
De acuerdo con los resultados, una cantidad de observaciones importantes quedan fuera del modelo. Para analizar la consistencia, se analizan algunos puntos extremos:
El primero de ellos es el punto extremo oriente, que corresponde al registro con id 58, una casa de estrato 5 del barrio Santa Mónica. La conclusión para este punto, que quedó ubicado cerca a la comuna 21, es que las coordenadas están erradas, Puede ser error de georreferenciación, o el uso
También existen dos puntos al extremo oeste, ID 8318 y 8319 que corresponden a casa en barrio la flora, estratos 4 y 5, bastante lejos de donde deberían estar.
El punto extremo sur es ID 6906, Casa estrato 6 del barrio Juanambú. Este barrio es de la zona noroeste.
Por otro lado, se encuentra una concentración importante de puntos alrededor de la carrera 44 con calle 14, zona centro geográfico. Aquí las coordenadas superpuestas pueden ser un error, o puede ser la entrada común a una propiedad horizontal, pero aún así no están en lo que se debería denominar zona norte, en el polígono de color rojo que marca el mapa. La etiqueta sólo puede visualizar al registro de id 3852, casa estrato 3 en Barrio Villa del Prado.
Se concluye que no todos los puntos están donde deberían estar. Esto lo podría estar causando lo siguiente:
Ahora bien, con el objetivo de obtener más datos para generar información de calidad, se genera un nuevo gráfico esta vez clasificando visualmente por estrato socioeconómico:
# Mapa: Segmentación estratos
cols <- colorFactor("viridis", domain = vivienda_casas$estrato)
mapa2 <- leaflet(vivienda_casas) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = zona_norte, color = "red", stroke = 1, opacity = 0.5) %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste0("<b>Id: </b>",id , "<br>",
"<b>Zona: </b>",zona, "<br>",
"<b>Tipo: </b>",tipo, "<br>",
"<b>Barrio: </b>",barrio, "<br>",
"<b>Estrato: </b>",estrato, "<br>",
"<b>Precio(mill): </b>",preciom, "<br>",
"<b>Habitaciones: </b>",habitaciones, "<br>",
"<b>Banios: </b>",banios, "<br>",
"<b>Parqueaderos: </b>",parqueaderos, "<br>"),
color = ~cols(estrato)) %>%
addLegend(data = vivienda_casas,
position = "bottomright",
pal = cols, values = ~estrato,
title = "Estrato",
opacity = 1)
mapa2
Como resultado, la estratificación socioeconómica tiene una distribución consistente. Como tema interesante, se ve que todas las “casas” que siendo “zona norte” quedaron al sur de la ciudad, son de estato 6. Sin embargo, una de ellas, ID 6033, quedó registrada como del barrio Acopi, que ya habíamos mencionado.
Ante la sospecha de que sea posible que los registros de “barrio” no sean consistentes, se hace el mismo análisis gráfico, pero esta vez filtrando para el barrio Acopi:
vivienda_casas_acopi <- filter(vivienda_casas, barrio =="acopi")
head(vivienda_casas_acopi, 3)
| 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 |
mapa3 <- leaflet(vivienda_casas_acopi) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = zona_norte, color = "red", stroke = 1, opacity = 0.5) %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste0("<b>Id: </b>",id , "<br>",
"<b>Zona: </b>",zona, "<br>",
"<b>Barrio: </b>",barrio, "<br>",
"<b>Estrato: </b>",estrato, "<br>",
"<b>Precio(mill): </b>",preciom, "<br>",
"<b>Habitaciones: </b>",habitaciones, "<br>",
"<b>Banios: </b>",banios, "<br>",
"<b>Parqueaderos: </b>",parqueaderos, "<br>"),
color = ~cols(estrato)) %>%
addLegend(data = vivienda_casas_acopi,
position = "bottomright",
pal = cols, values = ~estrato,
title = "Estrato",
opacity = 1)
mapa3
Aquí se podría inclusive sospechar que los 70 registros de vivienda para “Acopi” no sean los correctos. Es decir, es posible que uno de los registros ID 6808 sí sea una casa, con un valor de 1400 millones (Como se puede ver en el mapa en la etiqueta), pero que no quede en la zona norte ni esté en el Barrio Acopi.
Como recomendación, para esta base de datos se podría mejorar la calidad de los datos extrayendo información adicional, como puede ser la dirección del predio donde se ubica el inmueble, o el Número Predial Nacional (NPN)
2. Realice un análisis exploratorio de datos enfocado en la correlación entre la variable respuesta (precio de la casa) en función del área construida, estrato, numero de baños, numero de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.
Antes de empezar, se carga la librería plotly y se decide crear “Estrato” como una variable de tipo texto para que pase como categórica en la visualización de la data. La diferencia con la original, es que esta arranca con “e” mayúscula:
library(plotly)
Estrato <- as.character(vivienda_casas$estrato)
vivienda_casas <- cbind(vivienda_casas,Estrato) #Se corre una vez
plot_ly(vivienda_casas,x=~areaconst,y=~preciom,
type="scatter",
mode = "markers",
color=~Estrato, #Graficar estrato como variable categórica
symbol = ~Estrato
)
Los resultados aquí son teóricamente correctos: Se espera que una vivienda con mayor área tenga un mayor precio. Inclusive, aplicando una segmentación sobre el precio, como se puede ver en el siguiente gráfico, los datos se confirman:
plot_ly(vivienda_casas,x=~areaconst,y=~preciom,
type="scatter",
mode = "markers",
color=~Estrato, #Graficar estrato como variable categórica
symbol = ~Estrato,
frame = ~Estrato
)
p_estrato <- ggplot(vivienda_casas,aes(x=Estrato,y=preciom, fill=Estrato))+
geom_boxplot()+
labs(x="Estrato",y="Precio en Millones",title="Precios de vivienda tipo Casa en Zona Norte por Estrato") +
theme (panel.background = element_blank()
)
plotly::ggplotly(p_estrato)
Es importante aclarar que el estrato socieconómico es una variable categórica que se podría no incorporar con su valor a nivel (1, 2, 3, 4, 5, 6), sino con el nombre de la categoría en su orden: (bajo bajo, bajo, medio bajo, medio, medio alto, alto. )
Teóricamente se espera que los estratos socioeconómicos de mayores ingresos posean viviendas de mayor precio, y eso es lo que muestra el gráfico. Como complemento se presenta la siguiente tabla, donde se verifica que el promedio del precio es mayor a medida que el estrato socioeconómico es más alto:
library(table1)
table1(~preciom |Estrato, data=vivienda_casas)
| 3 (N=235) |
4 (N=161) |
5 (N=271) |
6 (N=55) |
Overall (N=722) |
|
|---|---|---|---|---|---|
| preciom | |||||
| Mean (SD) | 244 (120) | 439 (219) | 550 (246) | 818 (285) | 446 (268) |
| Median [Min, Max] | 215 [89.0, 1100] | 380 [160, 1800] | 480 [125, 1940] | 800 [430, 1600] | 390 [89.0, 1940] |
plot_ly(vivienda_casas,x=~banios,y=~preciom,type="scatter", mode = "markers",
color=~Estrato, symbol = ~Estrato)
Se nota una correlación positiva tambien entre el número de baños y el precio de la misma. No obstante se advierte en la calidad de los datos, que existe una cantidad de observaciones con cero baños a precios promedio más altos que las vivientas tipo casa con un solo baño. Una vivienda típica debería tener al menos un baño, por lo que se presume que los datos con cero, son errores de la extracción de los mismos.
table1(~preciom |banios, data=vivienda_casas)
| 0 (N=10) |
1 (N=17) |
2 (N=165) |
3 (N=187) |
4 (N=171) |
5 (N=101) |
6 (N=46) |
7 (N=11) |
8 (N=11) |
9 (N=1) |
10 (N=2) |
Overall (N=722) |
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| preciom | ||||||||||||
| Mean (SD) | 583 (348) | 184 (94.2) | 260 (164) | 391 (180) | 498 (249) | 592 (243) | 671 (299) | 809 (286) | 810 (427) | 1300 (NA) | 1040 (509) | 446 (268) |
| Median [Min, Max] | 435 [190, 1200] | 140 [89.0, 420] | 198 [120, 900] | 350 [130, 1500] | 440 [165, 1800] | 550 [300, 1650] | 610 [230, 1530] | 750 [450, 1600] | 690 [400, 1940] | 1300 [1300, 1300] | 1040 [680, 1400] | 390 [89.0, 1940] |
De igual forma se advierte que el precio aumenta a medida que aumentan el número de baños en las casas de la zona norte. No obstante, se señala que la mayoría de las observaciones se encuentran entre las casas que tienen entre 2 a 6 baños
plot_ly(vivienda_casas,x=~habitaciones,y=~preciom,type="scatter", mode = "markers",
color=~Estrato, symbol = ~Estrato)
En este gráfico no se alcanza a apreciar una correlación marcanda entre el número de habitaciones de una vivienda y su precio.
table1(~preciom |habitaciones, data=vivienda_casas)
| 0 (N=20) |
1 (N=2) |
2 (N=12) |
3 (N=171) |
4 (N=222) |
5 (N=137) |
6 (N=60) |
7 (N=42) |
8 (N=29) |
9 (N=14) |
10 (N=13) |
Overall (N=722) |
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| preciom | ||||||||||||
| Mean (SD) | 506 (264) | 210 (170) | 265 (126) | 311 (220) | 420 (215) | 537 (267) | 492 (207) | 549 (233) | 504 (306) | 569 (284) | 1010 (564) | 446 (268) |
| Median [Min, Max] | 408 [155, 1200] | 210 [89.0, 330] | 205 [125, 488] | 235 [110, 1400] | 381 [120, 1500] | 480 [170, 1600] | 445 [165, 1200] | 478 [220, 1200] | 440 [245, 1800] | 545 [245, 1300] | 680 [370, 1940] | 390 [89.0, 1940] |
Se debe revisar el hecho de que existan 20 viviendas con habitaciones en cero.
Para el caso del los parqueaderos, se imputa en cero los valores nulos, con el objertivo de visualizarlos y que puedan ser contados:
vivienda_casas$parqueaderos[is.na(vivienda_casas$parqueaderos)] <- 0
plot_ly(vivienda_casas,x=~parqueaderos,y=~preciom,type="scatter", mode = "markers",
color=~Estrato, symbol = ~Estrato)
En efecto se nota que a medida que aumenta el número de parqueaderos se puede ver un incremento en el precio de la vivienda
table1(~preciom |as.character(parqueaderos), data=vivienda_casas)
| 0 (N=287) |
1 (N=161) |
10 (N=1) |
2 (N=158) |
3 (N=49) |
4 (N=40) |
5 (N=11) |
6 (N=8) |
7 (N=5) |
8 (N=1) |
9 (N=1) |
Overall (N=722) |
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| preciom | ||||||||||||
| Mean (SD) | 395 (293) | 366 (178) | 350 (NA) | 487 (205) | 568 (297) | 659 (282) | 550 (88.2) | 812 (378) | 802 (345) | 950 (NA) | 720 (NA) | 446 (268) |
| Median [Min, Max] | 310 [110, 1800] | 340 [89.0, 1400] | 350 [350, 350] | 428 [180, 1500] | 480 [270, 1940] | 600 [270, 1600] | 540 [430, 690] | 675 [488, 1530] | 790 [430, 1300] | 950 [950, 950] | 720 [720, 720] | 390 [89.0, 1940] |
Se nota que 287 de los registros imputados en cero, están en null en la base de datos original, Esta situación se debe revisar.
En el caso de las zonas se solicita hacer análisis por zona, pero previamente se había filtrado a exclusivamente la zona norte. Por lo tanto, se vuelven a precargar las zonas:
vivienda_casas_1 <- filter(vivienda, tipo =="Casa")
Se elabora el gráfico:
p_zonas <- ggplot(vivienda_casas_1,aes(x=zona,y=preciom, fill=zona))+
geom_boxplot()+
labs(x="zona",y="Precio en Millones",title="Precios de vivienda tipo casa por Zona") +
theme (panel.background = element_blank()
)
plotly::ggplotly(p_zonas)
En el análisis, se encuentra que el precio depende de la zona, siendo la zona oeste de la ciudad la que maneja los precios más altos de vivienda y las zonas centro y oriente son las que manejan los menores precios de vivienda.
table1(~preciom |zona, data=vivienda_casas_1)
| Zona Centro (N=100) |
Zona Norte (N=722) |
Zona Oeste (N=169) |
Zona Oriente (N=289) |
Zona Sur (N=1939) |
Overall (N=3219) |
|
|---|---|---|---|---|---|---|
| preciom | ||||||
| Mean (SD) | 339 (162) | 446 (268) | 736 (398) | 245 (104) | 612 (378) | 540 (358) |
| Median [Min, Max] | 310 [148, 1100] | 390 [89.0, 1940] | 680 [135, 2000] | 235 [80.0, 750] | 480 [77.0, 1900] | 430 [77.0, 2000] |
3. Estime un modelo de regresión lineal múltiple con las variables del punto anterior (precio = f(área construida, estrato, número de cuartos, número de parqueaderos, número de baños ) ) e interprete los coeficientes si son estadísticamente significativos. Las interpretaciones deber están contextualizadas y discutir si los resultados son lógicos. Adicionalmente interprete el coeficiente R2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).
En primer lugar, se deberán crear algunas variables: El estrato socioeconómico es una variable categórica ordinal y se crearan dicótomas o dummies que se requieren. Se considera que los atributos de la vivienda, como habitaciones, baños y número de parqueaderos pueden considerarse variables seudocategóricas. Para efectos metodológicos se considerarán cuantitativas.
Por otro lado, hay un problema con la variable parqueadero, para lo que podemos optar por: 1. Eliminar los registros vacíos del modelo. 2. Asumir que al momento del ejercicio de web Scrapping, no se cargó un atributo para esta variable en vista de que no tenía un parqueadero, y se podria imputar en ceros.
Paso 1: Crear variables dicótomas a partir del estrato (Se usa el comando dummy_cols de la librería fastDummies, para mayor simplicidad en el código):
vivienda_casas <- filter(vivienda, zona == "Zona Norte" & tipo =="Casa")
require(fastDummies)
vivienda_casas <- dummy_cols(vivienda_casas,select_columns = "estrato")
glimpse(vivienda_casas)
## Rows: 722
## Columns: 17
## $ id <dbl> 1209, 1592, 4057, 4460, 6081, 7824, 7987, 3495, 141, 243,…
## $ zona <chr> "Zona Norte", "Zona Norte", "Zona Norte", "Zona Norte", "…
## $ piso <chr> "02", "02", "02", "02", "02", "02", "02", "03", NA, NA, N…
## $ estrato <dbl> 5, 5, 6, 4, 5, 4, 5, 5, 3, 3, 3, 3, 5, 3, 4, 4, 5, 5, 4, …
## $ preciom <dbl> 320, 780, 750, 625, 750, 600, 420, 490, 230, 190, 180, 50…
## $ areaconst <dbl> 150, 380, 445, 355, 237, 160, 200, 118, 160, 435, 120, 21…
## $ parqueaderos <dbl> 2, 2, NA, 3, 2, 1, 4, 2, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ banios <dbl> 4, 3, 7, 5, 6, 4, 4, 4, 2, 0, 3, 6, 5, 5, 3, 3, 4, 5, 5, …
## $ habitaciones <dbl> 6, 3, 6, 5, 6, 5, 5, 4, 3, 0, 3, 6, 4, 8, 4, 3, 4, 6, 4, …
## $ tipo <chr> "Casa", "Casa", "Casa", "Casa", "Casa", "Casa", "Casa", "…
## $ barrio <chr> "acopi", "acopi", "acopi", "acopi", "acopi", "acopi", "ac…
## $ longitud <dbl> -76.51341, -76.51674, -76.52950, -76.53179, -76.54044, -7…
## $ latitud <dbl> 3.47968, 3.48721, 3.38527, 3.40590, 3.36862, 3.42125, 3.4…
## $ estrato_3 <int> 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, …
## $ estrato_4 <int> 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, …
## $ estrato_5 <int> 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, …
## $ estrato_6 <int> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
Se constata que se crearon las variables “dummy” de cada uno de los estratos. Se opta por simplificar el dataset, para efectos de mejorar el análisis:
vivienda_casas <- vivienda_casas[,c(5,6,7,8,9,14,15,16,17)]
glimpse(vivienda_casas)
## Rows: 722
## Columns: 9
## $ preciom <dbl> 320, 780, 750, 625, 750, 600, 420, 490, 230, 190, 180, 50…
## $ areaconst <dbl> 150, 380, 445, 355, 237, 160, 200, 118, 160, 435, 120, 21…
## $ parqueaderos <dbl> 2, 2, NA, 3, 2, 1, 4, 2, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ banios <dbl> 4, 3, 7, 5, 6, 4, 4, 4, 2, 0, 3, 6, 5, 5, 3, 3, 4, 5, 5, …
## $ habitaciones <dbl> 6, 3, 6, 5, 6, 5, 5, 4, 3, 0, 3, 6, 4, 8, 4, 3, 4, 6, 4, …
## $ estrato_3 <int> 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, …
## $ estrato_4 <int> 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, …
## $ estrato_5 <int> 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, …
## $ estrato_6 <int> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
Respecto a la imputación de datos en cero (0) para los datos nulos en parqueadero, se efectúa una simulación por fuera y la variable ingresa siendo no representativa estadísticamente en el modelo. Se opta por dejar el dataset como está y que el comando lm elimine por defecto las observaciones que tengan registros vacios.
Se corre el modelo:
mod_casas <- lm(preciom ~ areaconst + estrato_4 + estrato_5 + estrato_6 + habitaciones + parqueaderos + banios, data = vivienda_casas)
summary(mod_casas)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato_4 + estrato_5 + estrato_6 +
## habitaciones + parqueaderos + banios, data = vivienda_casas)
##
## Residuals:
## Min 1Q Median 3Q Max
## -790.71 -74.72 -18.93 46.54 991.70
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 11.71883 27.15751 0.432 0.66631
## areaconst 0.68098 0.05283 12.890 < 2e-16 ***
## estrato_4 80.91006 24.55085 3.296 0.00106 **
## estrato_5 147.53872 22.70871 6.497 2.29e-10 ***
## estrato_6 281.68942 37.33161 7.546 2.74e-13 ***
## habitaciones 7.17906 5.69802 1.260 0.20839
## parqueaderos 24.22922 5.86635 4.130 4.36e-05 ***
## banios 18.09024 7.62857 2.371 0.01816 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 154.9 on 427 degrees of freedom
## (287 observations deleted due to missingness)
## Multiple R-squared: 0.607, Adjusted R-squared: 0.6006
## F-statistic: 94.24 on 7 and 427 DF, p-value: < 2.2e-16
Los resultados son los siguientes:
de las 722 observaciones iniciales, 287 salen por tener registros null en cualquiera de sus variables.
La prueba F y el p-value del modelo indica que el modelo globalmente es significativo desde el punto de vista estadístico. Los parámetros en su conjunto son estadísticamente difernetes a cero.
El intercepto a nivel indica que una vivienda en la zona norte cuesta 11 millones de forma autónoma. Se espera que el intercepto sea positivo, pero tiene un problema, es estadísticamente igual a cero (No significativo)
El parámetro de área indica que un metro cuadrado adicional aumenta el valor de la vivienda en 0.68 millones o lo que es igual, en 680 mil pesos para este subgrupo. Es teóricamente correcto, se supone que a mayor número de metros cuadrados, el precio debe ser mayor, y es estadísticamente significativa
Para el caso de estrato, no entra al juego la variable de estrato 3. Incluirla habría tenido un problema de estimación por multicolinealidad perfecta. Los parámetros para estrato 3, 4 y 5 son estadísticamente significativos, e indican que manteniendo todo lo demás constante, el ser estrato 4 le agrega 81 millones al precio, el ser estrato 5 le agrega 147 millones y el ser estrato 6 le agrega 281 millones al precio final de la vivienda.
En el caso de las habitaciones, el parámetro es estadísticamente no significativo, y posiblemente podria salir del modelo. El hecho que haya sido positivo(mayor a cero, teóricamente correcto), y que una habitación adicional le agrega 7 millones al precio de la vivienda, puede ser alentador, pero no relevante ni concluyente estadísticamente hablando.
En el caso de parqueaderos, el parámetro es estadísticamente significativo e indica que contar con un parqueadero adicional aumenta el valor de la vivienda en aproximadamente 24 millones de pesos.
En el caso del número de baños, el parámetro es estadísticamente significativo aunque con un nivel de confianza del 95%, mas bajo que los otros parámetros. Podemos concluir que un baño adicional valoriza la casa en 18 millones de pesos.
El R2 ajustado está en el orden del 60% lo que indica que los regresores en su conjunto explican las variaciones del 60% del precio de una vivienda. Al parecer, el ajuste del modelo puede no ser del todo preciso o satisfactorio, y podría generar incertidumbre al momento de escoger la mejor opción de vivienda o valorar correctamente una casa a partir de los atributos objeto del estudio.
Para mejorar el nivel de ajuste del modelo, podríamos optar por alguna de las siguientes características:
Incorporar nuevos determinantes del precio de la vivienda: Accesibilidad, servicios públicos disponibles, cercanía a dotacionales como parques, hospitales, escuelas, universidades, accesibilidad a transporte público, cercanía a zonas contaminadas o industriales
Pensar en una forma funcional diferente: Posiblemente el modelo no sea lineal.
Transformar variables, examinar estructuras de tipo log-lineal y todas las variantes conocidas.
4. Realice la validación de supuestos del modelo e interprete los resultados (no es necesario corregir en caso de presentar problemas, solo realizar sugerencias de que se podría hacer).
par(mfrow = c(2, 2))
plot(mod_casas)
0.
linealidad:
En la parte superior, se puede ver que el gráfico “Residuasl Vs Fitted” los residuos rotan alrededor del cero, lo que es un indicio de linealidad en los parámetros.
shapiro.test(mod_casas$residuals)
##
## Shapiro-Wilk normality test
##
## data: mod_casas$residuals
## W = 0.8487, p-value < 2.2e-16
El resultado, de acuerdo con el test de Shapiro-Wilk indica que los residuos no siguen una distribucion normal
2.Varianza constante de los errores, homocedasticidad:
library(lmtest)
bptest(mod_casas)
##
## studentized Breusch-Pagan test
##
## data: mod_casas
## BP = 82.976, df = 7, p-value = 3.4e-15
Los resultados de la prueba de Breusch-Pagan generan un p-valor menor a 5%, es decir, los residuos no tienen varianza constante, o son no son homocedásticos.
Se hace un gráfico con el objetivo de detectar posible relación lineal entre regresores:
library(corrplot)
pairs(vivienda_casas[, c("areaconst", "parqueaderos", "banios", "habitaciones")])
El
análisis visual puede denotar algún grado de relación lineal entre el
número de baños y el número de habitaciones (Lo cual es lógico, es de
presumir que a mayor número de habitaciones, una casa debería tener una
cantidad mayor de baños). Para efectos de determinar la presencia de un
grado no manejable de multicolinealidad en el modelo, se procede
analizando el factor inflador de la varianza:
library(car)
vif_mod_casas <- vif(mod_casas)
vif_mod_casas
## areaconst estrato_4 estrato_5 estrato_6 habitaciones parqueaderos
## 1.466064 1.974847 2.335881 1.521707 1.749911 1.228728
## banios
## 2.047730
Dado que no se presentan valores mayores a 5, se puede concluir que la posible relacion de linealidad observada en algunas variables aparentemente no representaría problemas representativos por la existencia de multicolinealidad.
En este modelo no realizaremos prueba de autocorrelación, dado que se trata de un modelo con datos en modo corte transversal. Este sería un problema si estamos manejando un problema de series de tiempo.
En resumen, no se resolverán los problemas del modelo de regresión lineal, pero se sugeriría optar por transformar variables (cambiar escalas, modelos log-lineales, entre otros.
solicitud_casa <- data.frame(areaconst = 200, parqueaderos = 1, banios = 2, habitaciones = 4,
estrato_4 =c(1,0),estrato_5 = c(0,1), estrato_6=c(0,0))
proy_precio_casa <- predict(mod_casas, newdata = solicitud_casa)
solicitud_casa$proy_precio_casa <- proy_precio_casa
solicitud_casa
| areaconst | parqueaderos | banios | habitaciones | estrato_4 | estrato_5 | estrato_6 | proy_precio_casa |
|---|---|---|---|---|---|---|---|
| 200 | 1 | 2 | 4 | 1 | 0 | 0 | 317.9507 |
| 200 | 1 | 2 | 4 | 0 | 1 | 0 | 384.5793 |
Los resultados indican que el precio de una casa en la zona norte con las características señaladas costaría unos 318 millones de pesos siempre y cuando se encuentre en el estrato 4, pero costaría unos 385 millones de pesos si el estrato socioeconómico es 5. En este punto, la consultora debería perfilar que la vivienda sea de estrato 4 como primera restricción, teniendo en cuenta el monto del crédito pre aprobado.
6. Con las predicciones del modelo sugiera potenciales ofertas que responda a la solicitud de la vivienda 1. Tenga encuentra que la empresa tiene crédito pre-aprobado de máximo 350 millones de pesos. Realice un análisis y presente en un mapa al menos 5 ofertas potenciales que debe discutir.
Al respecto, el producto que se podría entregar utilizando las herramientas, sería un mapa presentando qué viviendas se encuentran con un valor igual o menor a 350 millones de pesos y que tengan como mínimo la dotación pretendida.
vivienda_casas <- filter(vivienda, zona == "Zona Norte" & tipo =="Casa")
ofertas_casas <- subset(vivienda_casas, areaconst >= 200 & parqueaderos >=1 &
banios >= 2 & habitaciones >= 4 & estrato >= 4 &
preciom <= 350)
ofertas_casas <- ofertas_casas[order(-ofertas_casas$preciom), ]
ofertas_casas
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 4210 | Zona Norte | 01 | 5 | 350 | 200.0 | 3 | 3 | 4 | Casa | el bosque | -76.53010 | 3.48503 |
| 4209 | Zona Norte | 02 | 5 | 350 | 300.0 | 3 | 5 | 6 | Casa | el bosque | -76.53010 | 3.48577 |
| 4422 | Zona Norte | 02 | 5 | 350 | 240.0 | 2 | 3 | 6 | Casa | el bosque | -76.53136 | 3.48635 |
| 1270 | Zona Norte | NA | 5 | 350 | 203.0 | 2 | 2 | 5 | Casa | el bosque | -76.51448 | 3.48531 |
| 819 | Zona Norte | 02 | 5 | 350 | 264.0 | 2 | 3 | 4 | Casa | la flora | -76.50330 | 3.46412 |
| 937 | Zona Norte | 02 | 4 | 350 | 280.0 | 2 | 3 | 4 | Casa | la merced | -76.50603 | 3.46643 |
| 1163 | Zona Norte | NA | 5 | 350 | 216.0 | 2 | 2 | 4 | Casa | la merced | -76.51218 | 3.48181 |
| 5031 | Zona Norte | 03 | 4 | 350 | 350.0 | 1 | 4 | 5 | Casa | salomia | -76.53464 | 3.44987 |
| 1842 | Zona Norte | 02 | 5 | 350 | 240.0 | 2 | 3 | 4 | Casa | vipasa | -76.51800 | 3.48100 |
| 1943 | Zona Norte | NA | 5 | 350 | 346.0 | 1 | 2 | 4 | Casa | vipasa | -76.51847 | 3.47503 |
| 4483 | Zona Norte | 02 | 5 | 342 | 250.0 | 1 | 4 | 6 | Casa | el bosque | -76.53197 | 3.48752 |
| 4800 | Zona Norte | 01 | 5 | 340 | 250.0 | 2 | 4 | 4 | Casa | el bosque | -76.53300 | 3.46500 |
| 3453 | Zona Norte | NA | 5 | 340 | 240.0 | 2 | 5 | 6 | Casa | la campiña | -76.52640 | 3.48211 |
| 3101 | Zona Norte | 02 | 5 | 340 | 355.0 | 2 | 5 | 8 | Casa | san vicente | -76.52377 | 3.46384 |
| 1887 | Zona Norte | 01 | 5 | 340 | 203.0 | 2 | 3 | 4 | Casa | vipasa | -76.51803 | 3.48257 |
| 2544 | Zona Norte | 01 | 4 | 340 | 264.5 | 2 | 4 | 4 | Casa | vipasa | -76.52096 | 3.47665 |
| 7470 | Zona Norte | 02 | 4 | 340 | 264.0 | 2 | 5 | 7 | Casa | vipasa | -76.54980 | 3.37556 |
| 1822 | Zona Norte | NA | 4 | 340 | 295.0 | 2 | 2 | 4 | Casa | vipasa | -76.51777 | 3.48060 |
| 4267 | Zona Norte | 01 | 5 | 335 | 202.0 | 1 | 4 | 5 | Casa | el bosque | -76.53044 | 3.48399 |
| 3352 | Zona Norte | NA | 4 | 335 | 300.0 | 3 | 4 | 4 | Casa | el bosque | -76.52600 | 3.43400 |
| 952 | Zona Norte | 02 | 4 | 330 | 275.0 | 2 | 3 | 5 | Casa | la merced | -76.50647 | 3.47516 |
| 1108 | Zona Norte | 02 | 4 | 330 | 260.0 | 1 | 3 | 4 | Casa | la merced | -76.51060 | 3.48108 |
| 3043 | Zona Norte | NA | 5 | 330 | 275.0 | 2 | 3 | 5 | Casa | la merced | -76.52350 | 3.48329 |
| 1849 | Zona Norte | NA | 5 | 330 | 246.0 | 2 | 4 | 4 | Casa | prados del norte | -76.51800 | 3.47000 |
| 766 | Zona Norte | NA | 5 | 321 | 249.0 | 1 | 5 | 5 | Casa | la merced | -76.50291 | 3.46757 |
| 1343 | Zona Norte | 02 | 5 | 320 | 200.0 | 2 | 4 | 4 | Casa | la flora | -76.51524 | 3.48893 |
| 3053 | Zona Norte | 02 | 5 | 320 | 230.0 | 2 | 4 | 4 | Casa | la flora | -76.52353 | 3.48352 |
| 1144 | Zona Norte | NA | 4 | 320 | 200.0 | 2 | 4 | 4 | Casa | la merced | -76.51156 | 3.48029 |
| 1151 | Zona Norte | NA | 5 | 320 | 210.0 | 2 | 3 | 5 | Casa | urbanización la merced | -76.51200 | 3.47600 |
| 4458 | Zona Norte | 02 | 4 | 315 | 270.0 | 2 | 4 | 4 | Casa | el bosque | -76.53176 | 3.48780 |
| 1914 | Zona Norte | 02 | 5 | 300 | 205.0 | 2 | 5 | 6 | Casa | vipasa | -76.51832 | 3.48138 |
| 7432 | Zona Norte | 01 | 4 | 260 | 280.0 | 2 | 4 | 6 | Casa | los andes | -76.54973 | 3.42484 |
| 1009 | Zona Norte | NA | 5 | 250 | 243.0 | 1 | 4 | 5 | Casa | el bosque | -76.50755 | 3.47838 |
| 1020 | Zona Norte | 02 | 4 | 230 | 250.0 | 2 | 3 | 5 | Casa | la merced | -76.50799 | 3.47424 |
Se elabora el mapa de acuerdo con lo solicitado:
mapa_casas <- leaflet(ofertas_casas) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = zona_norte, color = "red", stroke = 1, opacity = 0.5) %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste0("<b>Id: </b>",id , "<br>",
"<b>Zona: </b>",zona, "<br>",
"<b>Tipo: </b>",tipo, "<br>",
"<b>Barrio: </b>",barrio, "<br>",
"<b>Estrato: </b>",estrato, "<br>",
"<b>Precio(mill): </b>",preciom, "<br>",
"<b>Habitaciones: </b>",habitaciones, "<br>",
"<b>Banios: </b>",banios, "<br>",
"<b>Parqueaderos: </b>",parqueaderos, "<br>")
)
mapa_casas
Se hace el filtrado de por lo menos 34 opciones de vivienda que cumplen con los criterios señalados y se señalan en el mapa. Se sugiere que se escoja la mejor opción teniendo en cuenta preferencias de ubicación y la evaluación de atributos adicionales como los mencionados anteriormente.
Dentro de la oferta, destacan las viviendas ubicadas en el barrio vipasa, id 1887, 1914, 1842 y 1882, por la ubicación céntrica y por ofrecer valores agregados por encima de lo esperado. No obstante hay muchos otros atributos que entran en juego al momento de escoger una vivienda definitiva.
7. Realice los pasos del 1 al 6 Para la segunda solicitud que tiene un crédito pre-aprobado por valor de $850 millones.
(Adicional un mapa con los puntos de las bases. Discutir si todos los puntos se ubican en la zona correspondiente o se presentan valores en otras zonas, por que?).
En primer lugar, se genera una pequeña tabla de contingencia sobre la base de datos general, con el objetivo de verificar la totalidad de tipo de vivienda, sean apartamentos o casas, respecto a la zona revelada en la base de datos:
table(vivienda$zona,vivienda$tipo)
##
## Apartamento Casa
## Zona Centro 24 100
## Zona Norte 1198 722
## Zona Oeste 1029 169
## Zona Oriente 62 289
## Zona Sur 2787 1939
Existen un total de 2787 registros para apartamentos en zona sur, lo que se validará al momento de generar la consulta. Se procede a efectuar el filtrado de la base de datos por los atributos solicitados, junto con los tres primeros registros de la consulta:
library(dplyr)
vivienda_aptos <- filter(vivienda, zona == "Zona Sur" & tipo =="Apartamento")
head(vivienda_aptos, 3)
| 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 |
Los tres primeros registros corresponden a los id 5098, 698 y 8199. Los barrios son Acopi, Aguablanca y Aguacatal. Por lo menos, Acopi es de la zona norte y Aguablanca de la zona oriental de la ciudad, por lo que se advierte que hay que revisar estos datos con cuidado.
table(vivienda_aptos$zona,vivienda_aptos$tipo)
##
## Apartamento
## Zona Sur 2787
En efecto, se concluye que la base de datos filtrada tiene 2787 registros, todos correspondientes a los atributos “Apartamento” en “zona sur”. Se efectúa una última validación :
glimpse(vivienda_aptos)
## Rows: 2,787
## Columns: 13
## $ id <dbl> 5098, 698, 8199, 1241, 5370, 6975, 5615, 6262, 7396, 6949…
## $ zona <chr> "Zona Sur", "Zona Sur", "Zona Sur", "Zona Sur", "Zona Sur…
## $ piso <chr> "05", "02", NA, NA, NA, "06", "08", NA, NA, NA, "10", "05…
## $ estrato <dbl> 4, 3, 6, 3, 3, 4, 3, 3, 3, 4, 3, 5, 6, 3, 3, 5, 5, 5, 6, …
## $ preciom <dbl> 290, 78, 875, 135, 135, 220, 210, 105, 115, 220, 230, 344…
## $ areaconst <dbl> 96, 40, 194, 117, 78, 75, 72, 68, 58, 84, 63, 107, 182, 7…
## $ parqueaderos <dbl> 1, 1, 2, NA, NA, 1, 2, NA, 1, NA, 1, 2, 2, 1, 1, 2, 1, 2,…
## $ banios <dbl> 2, 1, 5, 2, 1, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 4, 2, 4, 3, …
## $ habitaciones <dbl> 3, 2, 3, 3, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 2, 3, 3, …
## $ tipo <chr> "Apartamento", "Apartamento", "Apartamento", "Apartamento…
## $ barrio <chr> "acopi", "aguablanca", "aguacatal", "alameda", "alameda",…
## $ longitud <dbl> -76.53464, -76.50100, -76.55700, -76.51400, -76.53600, -7…
## $ latitud <dbl> 3.44987, 3.40000, 3.45900, 3.44100, 3.43600, 3.39109, 3.4…
Con lo anterior, se confirma que los registros de la base de datos quedaron correctamente filtrados. Ahora bien, se valida si efectivamente todos los 2787 registros quedaron ubicados en la zona sur. Para lo anterior, debemos definir qué es la zona sur de la ciudad de Cali, para lo que se acude a la información contenida en la Alcaldía de Cali, portal de Infraestructura de Datos Espaciales de Santiago de Cali - IDESC
La primera referencia para definir la zona sur es la siguiente:
” Zona Sur: Esta zona comprende el territorio que va desde la KR 50 con la CL 57 hasta la CL 5, vía por la cual se continúa hacia el sur de la ciudad hasta el Río Meléndez, siguiendo su cauce aguas arriba hasta el cruce con el límite del suelo urbano, por el que se continua hacia el sur de la ciudad hasta la KR 127 y por esta vía hasta la CL 18, punto en el cual se sigue el trazado (hacia el sur) del límite del suelo de expansión urbano hasta llegar al punto de inicio en la KR 50.
” Tomado de: https://www.cali.gov.co/planeacion/publicaciones/169423/zonas_geograficas_idesc/
Ahora bien, se construye un polígono con las comunas 17 y 22, disponibles como geodatabase con la información disponible en la siguiente página: https://www.cali.gov.co/planeacion/publicaciones/172941/datos_divipola_idesc/
Esto se almacena en archivo .shp, generado con Argis, previamente aplicando Dissolve (para que fuese un sólo polígono) y transformando el sistema de coordenadas planas a WGS 84.
Para el propósito, cargamos la libreríua leaflet y sf (para leer la capa), y se efectúa la visualización solicitada:
library(leaflet)
library(sf)
# Primer Mapa
zona_sur <- read_sf("C:/Users/lidersui/OneDrive - URBASER/Escritorio/divipola/ZONA_SUR_POLIGONO_wgs_f.shp")
mapa5 <- leaflet(vivienda_aptos) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = zona_sur, color = "orange", stroke = 1, opacity = 0.5) %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste0("<b>Id: </b>",id , "<br>",
"<b>Zona: </b>",zona, "<br>",
"<b>Tipo: </b>",tipo, "<br>",
"<b>Barrio: </b>",barrio, "<br>",
"<b>Estrato: </b>",estrato, "<br>",
"<b>Precio(mill): </b>",preciom, "<br>",
"<b>Habitaciones: </b>",habitaciones, "<br>",
"<b>Banios: </b>",banios, "<br>",
"<b>Parqueaderos: </b>",parqueaderos, "<br>")
)
mapa5
La situación respecto a la zona norte, se repite. Visualmente la mayoría de los puntos se encuentran dentro del polígono demarcado en la zona sur, pero una cantidad sustancial se encuentran por fuera.
Ahora bien, con el objetivo de obtener más datos para generar información de calidad, se genera un nuevo gráfico esta vez clasificando visualmente por estrato socioeconómico:
# Mapa: Segmentación estratos
cols <- colorFactor("viridis", domain = vivienda_aptos$estrato)
mapa5 <- leaflet(vivienda_aptos) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = zona_sur, color = "orange", stroke = 1, opacity = 0.5) %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste0("<b>Id: </b>",id , "<br>",
"<b>Zona: </b>",zona, "<br>",
"<b>Tipo: </b>",tipo, "<br>",
"<b>Barrio: </b>",barrio, "<br>",
"<b>Estrato: </b>",estrato, "<br>",
"<b>Precio(mill): </b>",preciom, "<br>",
"<b>Habitaciones: </b>",habitaciones, "<br>",
"<b>Banios: </b>",banios, "<br>",
"<b>Parqueaderos: </b>",parqueaderos, "<br>"),
color = ~cols(estrato)) %>%
addLegend(data = vivienda_aptos,
position = "bottomright",
pal = cols, values = ~estrato,
title = "Estrato",
opacity = 1)
mapa5
La concentración en el estrato 6 es en la zona sur de la ciudad y en la zona noroeste. Sin embargo, se visualizan viviendas de estrato 6 en la zona este de la ciudad, comuna 21, lo cual es improbable. Se debe tratar de un error de geocodificación, en el mismo sentido de los hallazgos de las casas de zona norte.
Para validar consistencia de la data, se toma un barrio de la zona sur de la ciudad (Ciudad Jardín)
vivienda_aptos_cjardin <- filter(vivienda_aptos, barrio =="ciudad jardín")
head(vivienda_aptos_cjardin, 3)
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 102 | Zona Sur | 01 | 5 | 370 | 87 | 2 | 3 | 3 | Apartamento | ciudad jardín | -76.48300 | 3.44500 |
| 2532 | Zona Sur | 01 | 4 | 275 | 96 | 2 | 2 | 0 | Apartamento | ciudad jardín | -76.52088 | 3.44889 |
| 3482 | Zona Sur | 01 | 5 | 248 | 73 | 1 | 2 | 3 | Apartamento | ciudad jardín | -76.52664 | 3.36417 |
mapa6 <- leaflet(vivienda_aptos_cjardin) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = zona_sur, color = "orange", stroke = 1, opacity = 0.5) %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste0("<b>Id: </b>",id , "<br>",
"<b>Zona: </b>",zona, "<br>",
"<b>Barrio: </b>",barrio, "<br>",
"<b>Estrato: </b>",estrato, "<br>",
"<b>Precio(mill): </b>",preciom, "<br>",
"<b>Habitaciones: </b>",habitaciones, "<br>",
"<b>Banios: </b>",banios, "<br>",
"<b>Parqueaderos: </b>",parqueaderos, "<br>"),
color = ~cols(estrato)) %>%
addLegend(data = vivienda_aptos_cjardin,
position = "bottomright",
pal = cols, values = ~estrato,
title = "Estrato",
opacity = 1)
mapa6
Aquí se podría inclusive sospechar que los 281 registros de vivienda para Ciudad Jardín no sean los correctos.
Como recomendación, para esta base de datos se podría mejorar la calidad de los datos extrayendo información adicional, como puede ser la dirección del predio donde se ubica el inmueble, o el Número Predial Nacional (NPN), al igual que las conclusiones para el análisis de casas de zona norte.
2. Realice un análisis exploratorio de datos enfocado en la correlación entre la variable respuesta (precio del apartamento) en función del área construida, estrato, numero de baños, numero de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.
Antes de empezar, se carga la librería plotly y se decide crear “Estrato” como una variable de tipo texto para que pase como categórica en la visualización de la data. La diferencia con la original, es que esta arranca con “e” mayúscula:
library(plotly)
Estrato <- as.character(vivienda_aptos$estrato)
vivienda_aptos <- cbind(vivienda_aptos,Estrato) #Se corre una vez
plot_ly(vivienda_aptos,x=~areaconst,y=~preciom,
type="scatter",
mode = "markers",
color=~Estrato, #Graficar estrato como variable categórica
symbol = ~Estrato
)
Los resultados aquí son teóricamente correctos: Se espera que una vivienda con mayor área tenga un mayor precio. Inclusive, aplicando una segmentación sobre el precio, como se puede ver en el siguiente gráfico, los datos se confirman:
plot_ly(vivienda_aptos,x=~areaconst,y=~preciom,
type="scatter",
mode = "markers",
color=~Estrato, #Graficar estrato como variable categórica
symbol = ~Estrato,
frame = ~Estrato
)
p_estrato2 <- ggplot(vivienda_aptos,aes(x=Estrato,y=preciom, fill=Estrato))+
geom_boxplot()+
labs(x="Estrato",y="Precio en Millones",title="Precios de vivienda tipo Apartamento en zona sur por Estrato") +
theme (panel.background = element_blank()
)
plotly::ggplotly(p_estrato2)
Es importante aclarar que el estrato socieconómico es una variable categórica que se podría no incorporar con su valor a nivel (1, 2, 3, 4, 5, 6), sino con el nombre de la categoría en su orden: (bajo bajo, bajo, medio bajo, medio, medio alto, alto. )
Teóricamente se espera que los estratos socioeconómicos de mayores ingresos posean viviendas de mayor precio, y eso es lo que muestra el gráfico. Como complemento se presenta la siguiente tabla, donde se verifica que el promedio del precio es mayor a medida que el estrato socioeconómico es más alto:
library(table1)
table1(~preciom |Estrato, data=vivienda_aptos)
| 3 (N=201) |
4 (N=1091) |
5 (N=1033) |
6 (N=462) |
Overall (N=2787) |
|
|---|---|---|---|---|---|
| preciom | |||||
| Mean (SD) | 141 (62.6) | 204 (67.5) | 294 (103) | 594 (256) | 297 (192) |
| Median [Min, Max] | 128 [75.0, 580] | 188 [78.0, 645] | 280 [93.0, 1250] | 580 [128, 1750] | 245 [75.0, 1750] |
plot_ly(vivienda_aptos,x=~banios,y=~preciom,type="scatter", mode = "markers",
color=~Estrato, symbol = ~Estrato)
Se nota una correlación positiva tambien entre el número de baños y el precio de la misma. No obstante, al igual que para casas zona norte se advierte en la calidad de los datos, que existe una cantidad de observaciones con cero baños con alto precio en relación. Una vivienda típica debería tener al menos un baño, por lo que se presume que los datos con cero, son errores de la extracción de los mismos.
table1(~preciom |banios, data=vivienda_aptos)
| 0 (N=6) |
1 (N=167) |
2 (N=1588) |
3 (N=662) |
4 (N=229) |
5 (N=123) |
6 (N=10) |
7 (N=1) |
8 (N=1) |
Overall (N=2787) |
|
|---|---|---|---|---|---|---|---|---|---|---|
| preciom | ||||||||||
| Mean (SD) | 456 (407) | 137 (45.9) | 221 (78.8) | 341 (132) | 547 (252) | 714 (239) | 1060 (360) | 980 (NA) | 730 (NA) | 297 (192) |
| Median [Min, Max] | 240 [148, 1000] | 126 [75.0, 320] | 220 [83.0, 840] | 310 [150, 1200] | 530 [152, 1750] | 690 [231, 1750] | 1150 [370, 1600] | 980 [980, 980] | 730 [730, 730] | 245 [75.0, 1750] |
De igual forma se advierte que el precio aumenta a medida que aumentan el número de baños en las casas de la zona norte. No obstante, se señala que la mayoría de las observaciones se encuentran entre los apartamentos que tienen entre 1 a 3 baños
plot_ly(vivienda_aptos,x=~habitaciones,y=~preciom,type="scatter", mode = "markers",
color=~Estrato, symbol = ~Estrato)
Al igual que en el caso de las casas en la zona norte, En este gráfico no se alcanza a apreciar una correlación marcanda entre el número de habitaciones de una vivienda y su precio. De hecho parecería que tener 4 habitaciones no le agrega valor respecto a los apartamentos de 3 habitaciones.
table1(~preciom |habitaciones, data=vivienda_aptos)
| 0 (N=8) |
1 (N=19) |
2 (N=463) |
3 (N=1902) |
4 (N=366) |
5 (N=24) |
6 (N=5) |
Overall (N=2787) |
|
|---|---|---|---|---|---|---|---|---|
| preciom | ||||||||
| Mean (SD) | 333 (288) | 218 (69.5) | 204 (105) | 291 (177) | 425 (238) | 603 (316) | 658 (510) | 297 (192) |
| Median [Min, Max] | 200 [148, 950] | 245 [93.0, 320] | 170 [75.0, 840] | 245 [83.0, 1750] | 350 [115, 1750] | 495 [231, 1280] | 575 [155, 1500] | 245 [75.0, 1750] |
Se debe revisar el hecho de que existan 8 de estos apartamentos con habitaciones en cero.
Para el caso del los parqueaderos, se imputa en cero los valores nulos, con el objertivo de visualizarlos y que puedan ser contados:
vivienda_aptos$parqueaderos[is.na(vivienda_aptos$parqueaderos)] <- 0
plot_ly(vivienda_aptos,x=~parqueaderos,y=~preciom,type="scatter", mode = "markers",
color=~Estrato, symbol = ~Estrato)
En efecto se nota que a medida que aumenta el número de parqueaderos se puede ver un incremento en el precio de la vivienda
table1(~preciom |as.character(parqueaderos), data=vivienda_aptos)
| 0 (N=406) |
1 (N=1551) |
10 (N=2) |
2 (N=718) |
3 (N=79) |
4 (N=31) |
Overall (N=2787) |
|
|---|---|---|---|---|---|---|---|
| preciom | |||||||
| Mean (SD) | 174 (103) | 230 (72.7) | 570 (537) | 431 (168) | 793 (350) | 913 (283) | 297 (192) |
| Median [Min, Max] | 150 [75.0, 1150] | 230 [78.0, 870] | 570 [190, 950] | 380 [140, 1200] | 700 [250, 1750] | 950 [240, 1580] | 245 [75.0, 1750] |
Se nota que 406 de los registros imputados en cero, están en null en la base de datos original, Esta situación se debe revisar, al igual que en el caso de casas en zona norte.
En el caso de las zonas se solicita hacer análisis por zona, pero previamente se había filtrado a exclusivamente la zona sur. Por lo tanto, se vuelven a precargar las zonas:
vivienda_aptos_1 <- filter(vivienda, tipo =="Apartamento")
Se elabora el gráfico:
p_zonas1 <- ggplot(vivienda_aptos_1,aes(x=zona,y=preciom, fill=zona))+
geom_boxplot()+
labs(x="zona",y="Precio en Millones",title="Precios de vivienda tipo apartamento por Zona") +
theme (panel.background = element_blank()
)
plotly::ggplotly(p_zonas1)
Al igual que para las casas de zona norte, en el análisis, se encuentra que el precio depende de la zona, siendo la zona oeste de la ciudad la que maneja los precios marcadamente más altos de vivienda y las zonas centro y oriente son las que manejan los menores precios de vivienda.
table1(~preciom |zona, data=vivienda_aptos_1)
| Zona Centro (N=24) |
Zona Norte (N=1198) |
Zona Oeste (N=1029) |
Zona Oriente (N=62) |
Zona Sur (N=2787) |
Overall (N=5100) |
|
|---|---|---|---|---|---|---|
| preciom | ||||||
| Mean (SD) | 187 (90.8) | 285 (200) | 668 (390) | 153 (165) | 297 (192) | 367 (289) |
| Median [Min, Max] | 153 [100, 400] | 250 [65.0, 1580] | 570 [85.0, 1950] | 115 [58.0, 1350] | 245 [75.0, 1750] | 279 [58.0, 1950] |
3. Estime un modelo de regresión lineal múltiple con las variables del punto anterior (precio = f(área construida, estrato, número de cuartos, número de parqueaderos, número de baños ) ) e interprete los coeficientes si son estadísticamente significativos. Las interpretaciones deber están contextualizadas y discutir si los resultados son lógicos. Adicionalmente interprete el coeficiente R2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).
En primer lugar, se deberán crear algunas variables: El estrato socioeconómico es una variable categórica ordinal y se crearan dicótomas o dummies que se requieren. Se considera que los atributos de la vivienda, como habitaciones, baños y número de parqueaderos pueden considerarse variables seudocategóricas. Para efectos metodológicos se considerarán cuantitativas.
Por otro lado, hay un problema con la variable parqueadero, para lo que podemos optar por: 1. Eliminar los registros vacíos del modelo. 2. Asumir que al momento del ejercicio de web Scrapping, no se cargó un atributo para esta variable en vista de que no tenía un parqueadero, y se podria imputar en ceros.
Paso 1: Crear variables dicótomas a partir del estrato (Se usa el comando dummy_cols de la librería fastDummies, para mayor simplicidad en el código):
vivienda_aptos <- filter(vivienda, zona == "Zona Sur" & tipo =="Apartamento")
vivienda_aptos <- dummy_cols(vivienda_aptos,select_columns = "estrato")
glimpse(vivienda_aptos)
## Rows: 2,787
## Columns: 17
## $ id <dbl> 5098, 698, 8199, 1241, 5370, 6975, 5615, 6262, 7396, 6949…
## $ zona <chr> "Zona Sur", "Zona Sur", "Zona Sur", "Zona Sur", "Zona Sur…
## $ piso <chr> "05", "02", NA, NA, NA, "06", "08", NA, NA, NA, "10", "05…
## $ estrato <dbl> 4, 3, 6, 3, 3, 4, 3, 3, 3, 4, 3, 5, 6, 3, 3, 5, 5, 5, 6, …
## $ preciom <dbl> 290, 78, 875, 135, 135, 220, 210, 105, 115, 220, 230, 344…
## $ areaconst <dbl> 96, 40, 194, 117, 78, 75, 72, 68, 58, 84, 63, 107, 182, 7…
## $ parqueaderos <dbl> 1, 1, 2, NA, NA, 1, 2, NA, 1, NA, 1, 2, 2, 1, 1, 2, 1, 2,…
## $ banios <dbl> 2, 1, 5, 2, 1, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 4, 2, 4, 3, …
## $ habitaciones <dbl> 3, 2, 3, 3, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 2, 3, 3, …
## $ tipo <chr> "Apartamento", "Apartamento", "Apartamento", "Apartamento…
## $ barrio <chr> "acopi", "aguablanca", "aguacatal", "alameda", "alameda",…
## $ longitud <dbl> -76.53464, -76.50100, -76.55700, -76.51400, -76.53600, -7…
## $ latitud <dbl> 3.44987, 3.40000, 3.45900, 3.44100, 3.43600, 3.39109, 3.4…
## $ estrato_3 <int> 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, …
## $ estrato_4 <int> 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ estrato_5 <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, …
## $ estrato_6 <int> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, …
Se constata que se crearon las variables “dummy” de cada uno de los estratos. Se opta por simplificar el dataset, para efectos de mejorar el análisis:
vivienda_aptos <- vivienda_aptos[,c(5,6,7,8,9,14,15,16,17)]
glimpse(vivienda_aptos)
## Rows: 2,787
## Columns: 9
## $ preciom <dbl> 290, 78, 875, 135, 135, 220, 210, 105, 115, 220, 230, 344…
## $ areaconst <dbl> 96, 40, 194, 117, 78, 75, 72, 68, 58, 84, 63, 107, 182, 7…
## $ parqueaderos <dbl> 1, 1, 2, NA, NA, 1, 2, NA, 1, NA, 1, 2, 2, 1, 1, 2, 1, 2,…
## $ banios <dbl> 2, 1, 5, 2, 1, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 4, 2, 4, 3, …
## $ habitaciones <dbl> 3, 2, 3, 3, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 2, 3, 3, …
## $ estrato_3 <int> 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, …
## $ estrato_4 <int> 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ estrato_5 <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, …
## $ estrato_6 <int> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, …
Se corre el modelo:
mod_aptos <- lm(preciom ~ areaconst + estrato_4 + estrato_5 + estrato_6 + habitaciones + parqueaderos + banios, data = vivienda_aptos)
summary(mod_aptos)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato_4 + estrato_5 + estrato_6 +
## habitaciones + parqueaderos + banios, data = vivienda_aptos)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1058.69 -39.21 0.38 36.96 898.14
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -28.38462 12.93336 -2.195 0.02828 *
## areaconst 1.28595 0.05105 25.189 < 2e-16 ***
## estrato_4 30.40026 9.55717 3.181 0.00149 **
## estrato_5 50.88889 9.61940 5.290 1.33e-07 ***
## estrato_6 204.40443 11.17300 18.294 < 2e-16 ***
## habitaciones -17.10675 3.70357 -4.619 4.06e-06 ***
## parqueaderos 62.13696 3.79229 16.385 < 2e-16 ***
## banios 41.95467 3.24893 12.913 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 92.52 on 2373 degrees of freedom
## (406 observations deleted due to missingness)
## Multiple R-squared: 0.7762, Adjusted R-squared: 0.7755
## F-statistic: 1175 on 7 and 2373 DF, p-value: < 2.2e-16
Los resultados son los siguientes:
de las 2787 observaciones iniciales, 406 salen por tener registros null en cualquiera de sus variables.
La prueba F y el p-value del modelo indica que el modelo globalmente es significativo desde el punto de vista estadístico. Los parámetros en su conjunto son estadísticamente diferentes a cero.
El intercepto a nivel arranca en -28 millones. Se espera que el intercepto sea positivo, y aquí, al contrario que en el modelo de casas zona norte, es estadísticamente significativo con un nivel de confianza del 95%
El parámetro de área indica que un metro cuadrado adicional aumenta el valor de la vivienda en 1.29 millones de pesos para este subgrupo. Es teóricamente correcto, se supone que a mayor número de metros cuadrados, el precio debe ser mayor, y el parámetro es estadísticamente significativo
Para el caso de estrato, no entra al juego la variable de estrato 3. Los parámetros para estrato 4, 5 y 6 son estadísticamente significativos, e indican que manteniendo todo lo demás constante, el ser estrato 4 le agrega 30 millones al precio, el ser estrato 5 le agrega 51 millones y el ser estrato 6 le agrega 204 millones al precio final de la vivienda.
En el caso de las habitaciones, el parámetro es estadísticamente significativo, pero contraintuitivo. No se concibe que tener una habitación adicional castigue el precio del apartamento en 17 millones de pesos.
En el caso de parqueaderos, el parámetro es estadísticamente significativo e indica que contar con un parqueadero adicional aumenta el valor de la vivienda en aproximadamente 62 millones de pesos.
En el caso del número de baños, el parámetro es estadísticamente significativo. Podemos concluir que un baño adicional valoriza el apartamento en 42 millones de pesos.
El R2 ajustado está en el orden del 77.6% lo que indica que los regresores en su conjunto explican las variaciones del 77.6% del precio de una vivienda. Este modelo con las mismas regresoras tiene un mejor nivel de bondad de ajuste que el modelo que se construyó para casas de zona norte.
Los criterios para mejorar la bondad de ajuste de este modelo, son los mismos que se explicaron para el caso de Casas de Zona Norte.
4. Realice la validación de supuestos del modelo e interprete los resultados (no es necesario corregir en caso de presentar problemas, solo realizar sugerencias de que se podría hacer).
par(mfrow = c(2, 2))
plot(mod_aptos)
1.
linealidad:
En la parte superior, se puede ver que el gráfico “Residuasl Vs Fitted” los residuos rotan alrededor del cero, lo que es un indicio de linealidad en los parámetros.
shapiro.test(mod_aptos$residuals)
##
## Shapiro-Wilk normality test
##
## data: mod_aptos$residuals
## W = 0.77823, p-value < 2.2e-16
El resultado, de acuerdo con el test de Shapiro-Wilk indica que los residuos no siguen una distribucion normal
3.Varianza constante de los errores, homocedasticidad:
library(lmtest)
bptest(mod_aptos)
##
## studentized Breusch-Pagan test
##
## data: mod_aptos
## BP = 709.57, df = 7, p-value < 2.2e-16
Los resultados de la prueba de Breusch-Pagan generan un p-valor menor a 5%, es decir, los residuos no tienen varianza constante, o son no son homocedásticos.
Se hace un gráfico con el objetivo de detectar posible relación lineal entre regresores:
library(corrplot)
pairs(vivienda_aptos[, c("areaconst", "parqueaderos", "banios", "habitaciones")])
El
análisis visual puede denotar algún grado de relación lineal entre el
área construída y el número de baños y habitaciones (Lo cual es lógico,
es de presumir que a mayor número de habitaciones y baños, el
apartamento debería tener mayor área). Para efectos de determinar la
presencia de un grado no manejable de multicolinealidad en el modelo, se
procede analizando el factor inflador de la varianza:
library(car)
vif_mod_aptos <- vif(mod_aptos)
vif_mod_aptos
## areaconst estrato_4 estrato_5 estrato_6 habitaciones parqueaderos
## 2.071289 5.785715 6.252606 5.313684 1.452564 1.790871
## banios
## 2.598186
En este modelo se presenta un posible problema de multicolinealidad que fuerzan las dummies de estrato. Esto puede estar explicando la mejora de la bondad del ajuste respecto al modelo de Casas de la zona norte.
En este modelo no realizaremos prueba de autocorrelación, dado que se trata de un modelo con datos en modo corte transversal. Este sería un problema si estamos manejando un problema de series de tiempo.
Al igual que en el caso de En resumen, no se resolverán los problemas del modelo de regresión lineal, pero se sugeriría optar por transformar variables (cambiar escalas, modelos log-lineales, entre otros)
5. Con el modelo identificado debe predecir el precio de la vivienda con las características de la primera solicitud.
solicitud_apto <- data.frame(areaconst = 300, parqueaderos = 3, banios = 3, habitaciones = 5,
estrato_4 =c(0,0),estrato_5 = c(1,0), estrato_6=c(0,1))
proy_precio_apto <- predict(mod_aptos, newdata = solicitud_apto)
solicitud_apto$proy_precio_apto <- proy_precio_apto
solicitud_apto
| areaconst | parqueaderos | banios | habitaciones | estrato_4 | estrato_5 | estrato_6 | proy_precio_apto |
|---|---|---|---|---|---|---|---|
| 300 | 3 | 3 | 5 | 0 | 1 | 0 | 635.0311 |
| 300 | 3 | 3 | 5 | 0 | 0 | 1 | 788.5467 |
Los resultados indican que el precio de un apartamento en la zona sur con las características señaladas costaría unos 635 millones de pesos siempre y cuando se encuentre en el estrato 5, Y unos 789 millones de pesos si el estrato socioeconómico es 6. En todo caso, el crédito preaprobado por 850 millones cubriría holgadamente cualquiera de las dos opciones de estrato.
6. Con las predicciones del modelo sugiera potenciales ofertas que responda a la solicitud de la vivienda 1. Tenga encuentra que la empresa tiene crédito pre-aprobado de máximo 850 millones de pesos. Realice un análisis y presente en un mapa al menos 5 ofertas potenciales que debe discutir.
Al respecto, el producto que se podría entregar utilizando las herramientas, sería un mapa presentando qué apartamentos se encuentran con un valor igual o menor a 850 millones de pesos y que tengan como mínimo la dotación pretendida.
vivienda_aptos <- filter(vivienda, zona == "Zona Sur" & tipo =="Apartamento")
ofertas_aptos <- subset(vivienda_aptos, areaconst >= 300 & parqueaderos >=3 &
banios >= 3 & habitaciones >= 5 & estrato >= 5 &
preciom <= 850)
ofertas_aptos <- ofertas_aptos[order(-ofertas_aptos$preciom), ]
ofertas_aptos
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 7182 | Zona Sur | NA | 5 | 730 | 573 | 3 | 8 | 5 | Apartamento | guadalupe | -76.548 | 3.408 |
| 7512 | Zona Sur | NA | 5 | 670 | 300 | 3 | 5 | 6 | Apartamento | seminario | -76.550 | 3.409 |
Se elabora el mapa de acuerdo con lo solicitado:
mapa_aptos <- leaflet(ofertas_aptos) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = zona_sur, color = "orange", stroke = 1, opacity = 0.5) %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste0("<b>Id: </b>",id , "<br>",
"<b>Zona: </b>",zona, "<br>",
"<b>Tipo: </b>",tipo, "<br>",
"<b>Barrio: </b>",barrio, "<br>",
"<b>Estrato: </b>",estrato, "<br>",
"<b>Precio(mill): </b>",preciom, "<br>",
"<b>Habitaciones: </b>",habitaciones, "<br>",
"<b>Banios: </b>",banios, "<br>",
"<b>Parqueaderos: </b>",parqueaderos, "<br>")
)
mapa_aptos
En este caso, se complica la oferta para apartamentos en zona norte con las condiciones señaladas. Las restricciones al momento de filtrar resulta en solo dos apartamentos. Están por fuera del polígono propuesto, pero bastante cerca y en la zona oeste, a lo que se le podría dar manejo. En todo caso, serían las únicas dos opciones disponibles con las que cuenta la inmobiliaria para ofrecerle a la multinacional, a diferencia del tipo Casa en Zona Norte, con 34 opciones disponibles.