Una empresa inmobiliaria líder en una gran ciudad está buscando comprender en profundidad el mercado de viviendas urbanas para tomar decisiones estratégicas más informadas. La empresa posee una base de datos extensa que contiene información detallada sobre diversas propiedades residenciales disponibles en el mercado. Se requiere realizar un análisis holístico de estos datos para identificar patrones, relaciones y segmentaciones relevantes que permitan mejorar la toma de decisiones en cuanto a la compra, venta y valoración de propiedades.
Se incluyen las librerías a utilizar
library(devtools)
library(knitr)
devtools::install_github("dgonxalex80/paqueteMODELOS", force = TRUE)
## ggplot2 (3.4.4 -> 3.5.0) [CRAN]
## magick (2.8.2 -> 2.8.3) [CRAN]
##
## There is a binary version available but the source version is later:
## binary source needs_compilation
## ggplot2 3.4.4 3.5.0 FALSE
##
## package 'magick' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\cdela\AppData\Local\Temp\Rtmp6ZferS\downloaded_packages
## ── R CMD build ─────────────────────────────────────────────────────────────────
##
✔ checking for file 'C:\Users\cdela\AppData\Local\Temp\Rtmp6ZferS\remotes52182e7b1996\dgonxalex80-paqueteMODELOS-796f588/DESCRIPTION'
##
─ preparing 'paqueteMODELOS':
## checking DESCRIPTION meta-information ...
✔ checking DESCRIPTION meta-information
##
─ checking for LF line-endings in source and make files and shell scripts
##
─ checking for empty or unneeded directories
## ─ building 'paqueteMODELOS_0.1.0.tar.gz'
##
##
library(paqueteMODELOS)
library(mice)
library(ggplot2)
library(tidyverse)
Cargamos y examinamos los datos
data(vivienda)
str(vivienda)
## spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id : num [1:8322] 1147 1169 1350 5992 1212 ...
## $ zona : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
## $ piso : chr [1:8322] NA NA NA "02" ...
## $ estrato : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
## $ preciom : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
## $ areaconst : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
## $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
## $ banios : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
## $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
## $ tipo : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
## $ barrio : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
## $ longitud : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
## $ latitud : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
## - attr(*, "spec")=
## .. cols(
## .. id = col_double(),
## .. zona = col_character(),
## .. piso = col_character(),
## .. estrato = col_double(),
## .. preciom = col_double(),
## .. areaconst = col_double(),
## .. parqueaderos = col_double(),
## .. banios = col_double(),
## .. habitaciones = col_double(),
## .. tipo = col_character(),
## .. barrio = col_character(),
## .. longitud = col_double(),
## .. latitud = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Mostramos data faltante (rotando los nombres para mejor visualización)
md.pattern(vivienda, rotate.names = TRUE)
## preciom id zona estrato areaconst banios habitaciones tipo barrio longitud
## 4808 1 1 1 1 1 1 1 1 1 1
## 1909 1 1 1 1 1 1 1 1 1 1
## 876 1 1 1 1 1 1 1 1 1 1
## 726 1 1 1 1 1 1 1 1 1 1
## 1 1 0 0 0 0 0 0 0 0 0
## 2 0 0 0 0 0 0 0 0 0 0
## 2 3 3 3 3 3 3 3 3 3
## latitud parqueaderos piso
## 4808 1 1 1 0
## 1909 1 1 0 1
## 876 1 0 1 1
## 726 1 0 0 2
## 1 0 0 0 12
## 2 0 0 0 13
## 3 1605 2638 4275
Creamos vector missing_data que contiene el número de valores faltantes por cada variable de vivienda
missing_data <-sapply(vivienda, function(x) sum(is.na(x)))
missing_data
## id zona piso estrato preciom areaconst
## 3 3 2638 3 2 3
## parqueaderos banios habitaciones tipo barrio longitud
## 1605 3 3 3 3 3
## latitud
## 3
Para visualizarlo mejor, usaremos la función kable del paquete knitr
kable(missing_data, format = "markdown", align = "c", col.names = "Missing Data")
| Missing Data | |
|---|---|
| id | 3 |
| zona | 3 |
| piso | 2638 |
| estrato | 3 |
| preciom | 2 |
| areaconst | 3 |
| parqueaderos | 1605 |
| banios | 3 |
| habitaciones | 3 |
| tipo | 3 |
| barrio | 3 |
| longitud | 3 |
| latitud | 3 |
Podemos observar que “piso” y “parqueaderos” son los atributos con mayor número de datos faltantes, con 2638 y 1605 respectivamente.
percent_missing_data <- function(x) {sum(is.na(x))/length(x)*100}
kable(apply(vivienda, 2, percent_missing_data), format = "markdown", align = "c", col.names = "Percent Missing Data")
| Percent Missing Data | |
|---|---|
| id | 0.0360490 |
| zona | 0.0360490 |
| piso | 31.6991108 |
| estrato | 0.0360490 |
| preciom | 0.0240327 |
| areaconst | 0.0360490 |
| parqueaderos | 19.2862293 |
| banios | 0.0360490 |
| habitaciones | 0.0360490 |
| tipo | 0.0360490 |
| barrio | 0.0360490 |
| longitud | 0.0360490 |
| latitud | 0.0360490 |
Podemos observar que el porcentaje de valores faltantes en piso es de 31.69% mientras que de parqueadero es el 19.28%.
Decidimos eliminar esas variables con datos faltantes al igual que las filas con datos faltantes, sin afectar la bd original.
vivienda_clean_columns <- vivienda[, !names(vivienda) %in% c("id","piso", "parqueaderos")]
vivienda_clean <- vivienda_clean_columns[complete.cases(vivienda_clean_columns), ]
vivienda_clean
Confirmamos que no tengamos datos faltantes.
md.pattern(vivienda_clean, rotate.names = TRUE)
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
## zona estrato preciom areaconst banios habitaciones tipo barrio longitud
## 8319 1 1 1 1 1 1 1 1 1
## 0 0 0 0 0 0 0 0 0
## latitud
## 8319 1 0
## 0 0
Estandarizamos variables numéricas, restandole la media y dividiendo por la desviación estandar:
vivienda_cp <- vivienda_clean %>% select_if(is.numeric) %>% scale()
head (vivienda_cp)
## estrato preciom areaconst banios habitaciones longitud
## [1,] -1.5872276 -0.5595498 -0.7339949 -0.07793773 1.6406840 0.9728466
## [2,] -1.5872276 -0.3465670 -0.3842568 -0.77811479 -0.4147626 0.9331875
## [3,] -1.5872276 -0.2552886 0.3152194 -0.77811479 0.2703863 0.7607566
## [4,] -0.6156201 -0.1031580 0.7349051 1.32241640 -0.4147626 -0.6549016
## [5,] 0.3559875 -0.5291236 -0.5940997 -0.77811479 -0.4147626 0.8682385
## [6,] 0.3559875 -0.5899759 -0.6150839 -0.07793773 -0.4147626 0.6670691
## latitud
## [1,] 0.3793708
## [2,] 0.3763219
## [3,] 0.4225243
## [4,] 0.4070454
## [5,] 0.9678065
## [6,] -1.1242009
prcomp(vivienda_cp)
## Standard deviations (1, .., p=7):
## [1] 1.7649945 1.2197986 0.9408170 0.8090903 0.6534211 0.4902176 0.4357175
##
## Rotation (n x k) = (7 x 7):
## PC1 PC2 PC3 PC4 PC5
## estrato 0.3596495 -0.46160840 0.29253122 -0.24988384 -0.47695341
## preciom 0.4947460 -0.06764679 0.25051923 -0.25237458 0.22943062
## areaconst 0.4556538 0.26756925 0.02809938 -0.12641620 0.64147176
## banios 0.4903682 0.18623745 -0.06882523 -0.01680433 -0.39400870
## habitaciones 0.2974110 0.54943309 -0.32731570 0.32355603 -0.33736244
## longitud -0.2672367 0.46217187 -0.01581921 -0.82481589 -0.17733905
## latitud -0.1338978 0.40072976 0.85950759 0.26942892 -0.08880096
## PC6 PC7
## estrato 0.501853021 0.17381740
## preciom -0.219896274 -0.72332891
## areaconst 0.292270190 0.45509101
## banios -0.652112622 0.37328490
## habitaciones 0.431734658 -0.31247031
## longitud 0.052076162 -0.01578471
## latitud -0.003114001 0.04739724
library(factoextra)
acp.pca <- prcomp(vivienda_cp)
fviz_eig(acp.pca, addlabels = TRUE, barfill = "green", col = "red", labelsize = 14, ggtitle = "Valores propios de PCA", xlab = "Dimensión", ylab = "Porcentaje de varianza")
Podemos observar que que el primer componente corresponde al 44.5% de variabilidad, el segundo 21.3%, 12.6% el tercero y 9.4% el cuarto. Realizaremos el análisis de componentes principales con estos primeros 4 componente pues suman el 87.8% de variabilidad.
Dimensión 1:
fviz_contrib(acp.pca,axes = 1, choice = "var", barfill = "green", col = "red",addlabels = TRUE)
Dimensión 2:
fviz_contrib(acp.pca,axes = 2, choice = "var", barfill = "green", col = "red",addlabels = TRUE)
Dimensión 3:
fviz_contrib(acp.pca,axes = 3, choice = "var", barfill = "green", col = "red",addlabels = TRUE)
Dimensión 4:
fviz_contrib(acp.pca,axes = 4, choice = "var", barfill = "green", col = "red",addlabels = TRUE)
fviz_pca_var(acp.pca,
col.var = "contrib",
gradient.cols = c("green", "red"),
repel = TRUE,
bg = "blue",
theme = "minimal",
legend.title = "Contribución",
arrowsize = 1
)
La Dim1 explica el 44.5% de la variabilidad, mientras que la Dim2 explica el 21.3%. Las variables como “areaconst”, “banios”, “precio” y “estrato” están fuertemente asociadas con la Dim1, mientras que “latitud” y “longitud” están más asociadas con la Dim2.
Se observa que la latitud no contribuye tanto, como si lo hace banios, areaconst.
filas<- rbind(vivienda_cp[110,],
vivienda_cp[1060,],
vivienda_cp[19,],
vivienda_cp[470,])
filas <- as.data.frame(filas)
rownames(filas) = c("Fila 114","Fila 106","Fila 19","Fila 470")
print(filas)
## estrato preciom areaconst banios habitaciones longitud
## Fila 114 0.3559875 0.5662165 1.9240146 -0.07793773 -2.4702091 -0.07495879
## Fila 106 -1.5872276 -1.0615807 -0.7899530 -1.47829186 -0.4147626 2.01260527
## Fila 19 0.3559875 -0.1487972 -0.5031678 -0.77811479 -0.4147626 -0.75433674
## Fila 470 1.3275950 1.4181477 0.5250622 1.32241640 0.2703863 -1.74696425
## latitud
## Fila 114 -0.66546026
## Fila 106 1.36369315
## Fila 19 0.14906237
## Fila 470 0.03179738
casos1 <- rbind(acp.pca$x[110,1:4],acp.pca$x[1060,1:4]) # CP1
rownames(casos1) = c("110","1060")
casos1 <- as.data.frame(casos1)
casos2 <- rbind(acp.pca$x[019,1:4], acp.pca$x[470,1:4]) # CP2
rownames(casos2) = c("019","470")
casos2 <- as.data.frame(casos2)
fviz_pca_ind(acp.pca, col.ind = "gray", gradient.cols = c("green", "orange", "purple")) +
geom_point(data = casos1, aes(x = PC1, y = PC2), color = "red", size = 5) +
geom_point(data = casos2, aes(x = PC1, y = PC2), color = "blue", size = 5)
Obtenemos el número de elementos en el conjunto de datos
length(vivienda_clean$tipo)
## [1] 8319
Obtenemos el número de filas de la matriz
nrow(acp.pca$x)
## [1] 8319
fviz_pca_biplot(
acp.pca,
habillage = vivienda_clean$tipo,
repel = TRUE,
col.var = "red",
col.ind = c("green", "blue")
)
De la anterior gráfica podemos analizar que el tipo de vivienda apartamento, tiene variables con mayor peso explicativo relacionado con metro cuadrado y estrato. Mientras que el tipo de vivienda casa las variables con mayor peso son habitaciones, areaconst, y banios
fviz_pca_biplot(
acp.pca,
repel = TRUE,
habillage = vivienda_clean$zona,
col.var = "red",
col.ind = c("green", "purple")
)
Con respecto a la zona, podemos ver que influye en la variación. Por ejemplo:
Zona norte priman habitacion, longitud y latitud.
Zona sur: areaconst
Zona oeste: banios, preciom