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.
options(repos = "http://cran.us.r-project.org")
install.packages("paqueteMODELOS")
## Warning: package 'paqueteMODELOS' is not available for this version of R
##
## A version of this package for your version of R might be available elsewhere,
## see the ideas at
## https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
library(paqueteMODELOS)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
data(vivienda)
head(vivienda)
vivienda = select (vivienda, id:tipo)
vivienda = select (vivienda, -id)
head(vivienda)
summary(vivienda)
## zona piso estrato preciom
## Length:8322 Length:8322 Min. :3.000 Min. : 58.0
## Class :character Class :character 1st Qu.:4.000 1st Qu.: 220.0
## Mode :character Mode :character Median :5.000 Median : 330.0
## Mean :4.634 Mean : 433.9
## 3rd Qu.:5.000 3rd Qu.: 540.0
## Max. :6.000 Max. :1999.0
## NA's :3 NA's :2
## areaconst parqueaderos banios habitaciones
## Min. : 30.0 Min. : 1.000 Min. : 0.000 Min. : 0.000
## 1st Qu.: 80.0 1st Qu.: 1.000 1st Qu.: 2.000 1st Qu.: 3.000
## Median : 123.0 Median : 2.000 Median : 3.000 Median : 3.000
## Mean : 174.9 Mean : 1.835 Mean : 3.111 Mean : 3.605
## 3rd Qu.: 229.0 3rd Qu.: 2.000 3rd Qu.: 4.000 3rd Qu.: 4.000
## Max. :1745.0 Max. :10.000 Max. :10.000 Max. :10.000
## NA's :3 NA's :1605 NA's :3 NA's :3
## tipo
## Length:8322
## Class :character
## Mode :character
##
##
##
##
vivienda_na <- colSums(is.na(vivienda)) %>% as.data.frame()
print(vivienda_na)
## .
## zona 3
## piso 2638
## estrato 3
## preciom 2
## areaconst 3
## parqueaderos 1605
## banios 3
## habitaciones 3
## tipo 3
En este punto se pueden tomar dos decisiones, la primera es, no considerar la variable piso la cual tiene un porcentaje alto de valores sin datos y que al eliminarlos la muestra reduciria su tamaño. Esta opcion asume que la variable piso no aportaria mucho en el analisis por lo tanto se eliminaria y el tamaño de la muestra seguiria estando completo
La segunda opcion es eliminar los datos NA de la variable piso asumiendo que esta sí representa interes para el analisis, con esta opción la muestra se reducira un 30% pero se mantendria la variable piso para su analisis.
Seleccionamos la opción dos para no descartar ninguna variable.
vivienda = na.omit(vivienda)
head (vivienda)
vivienda_na2 <- colSums(is.na(vivienda)) %>% as.data.frame()
print(vivienda_na2)
## .
## zona 0
## piso 0
## estrato 0
## preciom 0
## areaconst 0
## parqueaderos 0
## banios 0
## habitaciones 0
## tipo 0
Las categorias quedaran asi:
Zona Centro: 1 Zona Norte: 2 Zona Oeste: 3 Zona Oriente: 4 Zona Sur: 5
vivienda <- vivienda %>% mutate(zona = case_when (
zona == "Zona Centro" ~ 1,
zona == "Zona Norte" ~ 2,
zona == "Zona Oeste" ~ 3,
zona == "Zona Oriente" ~ 4,
zona == "Zona Sur" ~ 5, ))
vivienda$zona <- as.numeric(vivienda$zona)
Casa: 1 Apartamento: 2
vivienda <- vivienda %>% mutate(tipo = case_when ( tipo == "Casa" ~ 1,
tipo == "Apartamento" ~ 2))
vivienda$tipo <- as.numeric(vivienda$tipo)
vivienda$piso <- as.numeric(vivienda$piso)
head(vivienda)
library(corrplot)
## corrplot 0.92 loaded
matrizcor <- cor(vivienda)
corrplot (matrizcor, method = "number", number.cex = 0.5)
Las correlaciones positivas que mas destacan son:
areaconst y preciom: 0.7.
Parqueaderos y preciom: 0.7.
banios y preciom: 0.69.
banios y areaconst: 0.68.
preciom y estrato: 0.59.
Las correlaciones negativas que mas destacan son:
tipo y areaconst: - 0.58.
habitaciones y tipo: -0.57.
Realizamos la estandarización de las variables para que tengan media 0 y desviación estándar 1 esto nos ayuda a estandarizar las distancias entre observaciones.
viviendapca <- scale(vivienda)
head (viviendapca, n = 6)
## zona piso estrato preciom areaconst parqueaderos
## [1,] 0.7275272 -0.7053307 -0.9046263 -0.1756310 0.7609789 1.0779092
## [2,] -1.6547322 -1.0793910 0.1749079 -0.6055839 -0.6129041 -0.7415001
## [3,] -1.6547322 -1.0793910 0.1749079 -0.6670057 -0.6345970 -0.7415001
## [4,] -1.6547322 -1.0793910 -0.9046263 -0.7284276 -0.8876807 0.1682046
## [5,] -1.6547322 -1.0793910 0.1749079 -0.4520293 -0.2730489 0.1682046
## [6,] -1.6547322 -0.7053307 0.1749079 -0.4213184 -0.1790463 0.1682046
## banios habitaciones tipo
## [1,] 1.3178809 -0.4241459 -1.3987647
## [2,] -0.9022913 -0.4241459 0.7147679
## [3,] -0.1622339 -0.4241459 0.7147679
## [4,] -0.9022913 -0.4241459 0.7147679
## [5,] -0.1622339 0.3272519 0.7147679
## [6,] 0.5778235 1.8300475 -1.3987647
prcomp(viviendapca)
## Standard deviations (1, .., p=9):
## [1] 1.9807435 1.3038276 1.0065797 0.8880937 0.6917289 0.6058975 0.5574084
## [8] 0.4943040 0.4172944
##
## Rotation (n x k) = (9 x 9):
## PC1 PC2 PC3 PC4 PC5
## zona -0.02543955 -0.16404488 0.927132120 -0.30571078 0.0792994
## piso 0.14110002 0.47067593 -0.154481596 -0.76787482 0.2210911
## estrato -0.22413900 0.53649200 0.246911243 0.24621865 -0.5187323
## preciom -0.41455699 0.31330628 0.015040316 0.07954319 0.1161470
## areaconst -0.44151818 -0.04940037 -0.094924610 -0.04254934 0.2165833
## parqueaderos -0.39125435 0.20508436 0.033326960 0.13250822 0.5627818
## banios -0.43986424 0.04969392 -0.012030129 -0.20192873 -0.3205302
## habitaciones -0.32832942 -0.34127243 -0.212162323 -0.43466711 -0.4079579
## tipo 0.32870777 0.44959161 0.009547411 -0.02964557 -0.1716275
## PC6 PC7 PC8 PC9
## zona -0.03797742 0.10381102 0.0223395978 -0.020064740
## piso 0.23029631 -0.20009533 0.0556938762 -0.001012726
## estrato 0.18384548 -0.28738369 0.3817542272 0.095609530
## preciom 0.13255630 0.35640811 -0.2009827307 -0.724531754
## areaconst 0.34918527 0.53100050 0.2993308600 0.501399059
## parqueaderos -0.57395890 -0.32772873 0.1412620713 0.112596771
## banios -0.10575830 -0.08878210 -0.7261119848 0.337764342
## habitaciones -0.37495877 0.03241888 0.4165040698 -0.245426552
## tipo -0.53945613 0.58418157 -0.0007715692 0.164654009
vivipca <- (prcomp(viviendapca))
library(ggplot2)
library(ggsignif)
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
fviz_eig(vivipca, addlabels = TRUE, ylim = c(0, 55))
fviz_contrib(vivipca, choice = "var", axes = 1, top = 10)
fviz_contrib(vivipca, choice = "var", axes = 2, top = 10)
fviz_contrib(vivipca, choice = "var", axes = 3, top = 10)
En el gráfico de correlación entre variables, podemos observar que la primera componente está relacionada con el precio, el número de parqueaderos, el número de baños y el área construida de las viviendas. Estas variables presentan una correlación positiva entre sí, ya que están agrupadas. El segundo componente tiene asociado las variables estrato, piso, tipo y habitaciones las cuales siguen teniendo correlación positiva y explican el resto de la varianza. El tercer componente tiene una particularidad y es que su capacidad para explicar la varianza es relativamente baja en comparación con los dos primeros componentes pues esta influenciado solo por la variable zona.
get_pca_var(vivipca)$contrib[,1:3]
## Dim.1 Dim.2 Dim.3
## zona 0.06471708 2.6910722 85.957396733
## piso 1.99092149 22.1535828 2.386456357
## estrato 5.02382904 28.7823667 6.096516170
## preciom 17.18574952 9.8160822 0.022621110
## areaconst 19.49383001 0.2440397 0.901068167
## parqueaderos 15.30799680 4.2059593 0.111068629
## banios 19.34805484 0.2469485 0.014472400
## habitaciones 10.78002113 11.6466869 4.501285127
## tipo 10.80488009 20.2132616 0.009115306
fviz_pca_var(vivipca, col.var = "contrib", gradient.cols = c("#FF7F00", "#034D94"),
repel = TRUE)
varianza_expl <- vivipca$sdev^2/sum(vivipca$sdev^2)
round(varianza_expl*100, 2)
## [1] 43.59 18.89 11.26 8.76 5.32 4.08 3.45 2.71 1.93
varianza_acum <- cumsum(varianza_expl)
round(varianza_acum*100, 2)
## [1] 43.59 62.48 73.74 82.50 87.82 91.90 95.35 98.07 100.00
ggplot(data = data.frame(varianza_acum, pc = 1:9),
aes(x = pc, y = varianza_acum, group = 1)) +
geom_point() +
geom_line() +
theme_bw() +
labs(x = "Componente principal",
y = "Prop. varianza explicada acumulada")
El analisis de componentes principales ha podido identificar inicialmente 3 grandes componentes que en su acumulado representan el 73,74% de la varianza del conjunto de datos esto teniendo en cuenta el metodo del codo con la varianza acumulada que elige el numero de componentes en el punto donde la curva se aplana. Estos tres componentes principales capturan la mayoría de la varianza en los datos sin embargo haciendo un zoom en el componente principale 3, este está principalmente influenciado por la variable “zona” por lo que su capacidad para explicar la varianza es relativamente baja en comparación con los dos primeros componentes.
Dado que los dos primeros componentes principales explican la mayoría de la varianza y parecen capturar aspectos clave tanto económicos como arquitectónicos de las viviendas, se recomenda enfocarse en ellos para obtener una comprensión profunda de las relaciones y patrones presentes en los datos. El tercer componente, aunque refleja una variable importante (zona), puede no aportar tanta información como los dos primeros. Sin embargo, podría ser relevante en casos específicos donde se quiera explorar la variabilidad geográfica de las viviendas.
El componente Principal 1 está fuertemente influenciado por las variables relacionadas con las características físicas y financieras de las viviendas, como el precio, el número de parqueaderos, el número de baños y el área construida. Indica una dimensión que refleja el valor y tamaño de las viviendas, junto con los aspectos prácticos como el espacio de estacionamiento y las comodidades.Podemos notar que a mayor número de parqueaderos, mayor será el precio, y a mayor número de baños, mayor será el área construida de la vivienda.
Componente Principal 2 agrupa variables como el estrato, el piso, el tipo de vivienda y el número de habitaciones. Aquí se reflejan las diferencias en la clasificación socioeconómica y características arquitectónicas de las viviendas. CP2 sugiere una dimensión que podría relacionarse con el perfil y estilo de vida de los habitantes.
fviz_nbclust(viviendapca, kmeans, method = "silhouette")
Se puede observar la silueta con diferentes números de clúster, donde con un clúster de tamaño 2 se obtiene la mayor silueta.
Escalamos las variables
viviendaclu <- scale (vivienda)
head(viviendaclu)
## zona piso estrato preciom areaconst parqueaderos
## [1,] 0.7275272 -0.7053307 -0.9046263 -0.1756310 0.7609789 1.0779092
## [2,] -1.6547322 -1.0793910 0.1749079 -0.6055839 -0.6129041 -0.7415001
## [3,] -1.6547322 -1.0793910 0.1749079 -0.6670057 -0.6345970 -0.7415001
## [4,] -1.6547322 -1.0793910 -0.9046263 -0.7284276 -0.8876807 0.1682046
## [5,] -1.6547322 -1.0793910 0.1749079 -0.4520293 -0.2730489 0.1682046
## [6,] -1.6547322 -0.7053307 0.1749079 -0.4213184 -0.1790463 0.1682046
## banios habitaciones tipo
## [1,] 1.3178809 -0.4241459 -1.3987647
## [2,] -0.9022913 -0.4241459 0.7147679
## [3,] -0.1622339 -0.4241459 0.7147679
## [4,] -0.9022913 -0.4241459 0.7147679
## [5,] -0.1622339 0.3272519 0.7147679
## [6,] 0.5778235 1.8300475 -1.3987647
set.seed(1)
modelkmeans <- kmeans(viviendaclu, 2)
viviendaclu <- data.frame(viviendaclu,modelkmeans$cluster)
aggregate(vivienda,
by = list(viviendaclu$modelkmeans.cluster),
FUN = median)
library(flextable)
Numcluste = table(viviendaclu$modelkmeans.cluster)%>%
as.data.frame()
colnames(Numcluste)=c("Cluster", "Frecuencia")
flextable(Numcluste)
Cluster | Frecuencia |
|---|---|
1 | 1,585 |
2 | 3,223 |
viviendakmeans = kmeans(viviendaclu, centers = 2)
vivienda$cluster = viviendakmeans$cluster
vivienda$cluster = as.character(vivienda$cluster)
head(vivienda, n = 6)
fviz_cluster(list(data = viviendaclu[1:9],
cluster = viviendaclu$modelkmeans.cluster),
palette = c("#2E9FDF", "#E7B800", "#FC4E07"),
ellipse.type = "convex",repel = F,
show.clust.cent = FALSE, ggtheme = theme_minimal())
med_clus <- aggregate(cbind(piso, estrato, preciom, areaconst, parqueaderos,
banios, tipo) ~ cluster,
data = vivienda, FUN = function(x) c(Media = round(mean(x), 2)))
colnames(med_clus)=c("Cluster", "Piso", "Estrato", "Precio",
"Area construida", "Parqueaderos", "Baños",
"tipo")
flextable(med_clus)
Cluster | Piso | Estrato | Precio | Area construida | Parqueaderos | Baños | tipo |
|---|---|---|---|---|---|---|---|
1 | 4.38 | 4.67 | 309.82 | 106.42 | 1.38 | 2.54 | 1.88 |
2 | 2.88 | 5.19 | 756.86 | 313.73 | 2.70 | 4.61 | 1.22 |
El análisis de clustering revela la presencia de dos clusters distintos con características notables. Se han agrupado las variables con base en sus atributos.
Como se puede observar en la tabla med_clus podemos relacionar lo siguiente:
En el cluster #1 podemos encontrar viviendas pequeñas con menos baños y un parqueadero en promedio, estas viviendas son las mas economicas del mercado.
En el cluster #2 se observa que las viviendas estan en estratos mas altos, son viviendas mas grandes y mas costosas a su ves tienen mas baños y parqueaderos.
Se puede decir que en el cluster 1 estan las viviendas mas accesibles a los clientes y en el cluster 2 estan las viviendas mas lujosas con mejores condiciones habitacionales.
viviacs = table(vivienda$zona, vivienda$estrato)
str(viviacs)
## 'table' int [1:5, 1:4] 33 141 19 94 147 3 184 51 2 973 ...
## - attr(*, "dimnames")=List of 2
## ..$ : chr [1:5] "1" "2" "3" "4" ...
## ..$ : chr [1:4] "3" "4" "5" "6"
viviacs
##
## 3 4 5 6
## 1 33 3 0 0
## 2 141 184 482 79
## 3 19 51 181 502
## 4 94 2 1 0
## 5 147 973 1195 721
library(FactoMineR)
chisq.test(viviacs)
## Warning in chisq.test(viviacs): Chi-squared approximation may be incorrect
##
## Pearson's Chi-squared test
##
## data: viviacs
## X-squared = 2172.8, df = 12, p-value < 2.2e-16
En este caso la hipótesis nula es la independencia de la variables categóricas. El nivel de significancia establecido es 0.05. El resultado rechaza en cualquier caso la hipótesis nula, por lo tanto, hay algún grado de relación entre las variables.
acs <- CA(viviacs)
eigenvalues <- acs$eig
print(eigenvalues)
## eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.29526876 65.338252 65.33825
## dim 2 0.13919088 30.800716 96.13897
## dim 3 0.01744831 3.861032 100.00000
En el grafico se puede observar que:
Las viviendas de estratos bajos (3) estan ubicadas en la zona centro. Las viviendas que están ubicadas en las zonas Norte y Sur son principalmente de estratos 4 y 5. Las mejores viviendas se encuentran ubicadas en la zona oeste.
El análisis de correspondencia Simple (ACS) nos muestra una relacion entre las variables categorías zona y estrato. Con esta relacion podemos determinar donde ubicariamos mejor un proyecto de edificación de acuerdo a su cliente objetivo segun el estrato para evitar construir edificaciones lujosas en zonas donde el cliente objetivo normalmente no compraria.