#Preparación de 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>
kable(head(vivienda), caption = "Primeras filas del conjunto de datos de 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 |
#Análiis de data set
vivienda2 <- data.frame(vivienda)
md.pattern(vivienda2, 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
Se encuentran 4808 registros sin datos faltantes, también se encontraron 3514 registros con datos faltante, en donde 2638 resgistros no tiene datos en la variable piso, 1605 les falta información en la variable parqueadero
A continuación se imputan los valores de las variables parqueaderos y piso por el valor de 0 en los registros que no tengan datos.
suppressMessages({
# Imputar valores faltantes con 0
vivienda2$parqueaderos[is.na(vivienda2$parqueaderos)] <- 0
# Imputar valores faltantes con 0
vivienda2$piso[is.na(vivienda2$piso)] <- 0
# Eliminar datos faltantes
vivienda2 <- na.omit(vivienda2)
# Visualizar data
md.pattern(vivienda2, rotate.names = TRUE)
})
/\ /\
{ `---' }
{ O O }
==> V <== No need for mice. This data set is completely observed.
\ \|/ /
`-----'
id zona piso estrato preciom areaconst parqueaderos banios habitaciones
8319 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0
tipo barrio longitud latitud
8319 1 1 1 1 0
0 0 0 0 0
vivienda2$piso <- as.numeric(vivienda2$piso)
vivienda2$estrato <- as.numeric(vivienda2$estrato)
vivienda2$preciom <- as.numeric(vivienda2$preciom)
vivienda2$areaconst <- as.numeric(vivienda2$areaconst)
vivienda2$banios <- as.numeric(vivienda2$banios)
vivienda2$habitaciones <- as.numeric(vivienda2$habitaciones)
kable(head(vivienda2), caption = "Data con conversión de variables")
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1147 | Zona Oriente | 0 | 3 | 250 | 70 | 1 | 3 | 6 | Casa | 20 de julio | -76.51168 | 3.43382 |
| 1169 | Zona Oriente | 0 | 3 | 320 | 120 | 1 | 2 | 3 | Casa | 20 de julio | -76.51237 | 3.43369 |
| 1350 | Zona Oriente | 0 | 3 | 350 | 220 | 2 | 2 | 4 | Casa | 20 de julio | -76.51537 | 3.43566 |
| 5992 | Zona Sur | 2 | 4 | 400 | 280 | 3 | 5 | 3 | Casa | 3 de julio | -76.54000 | 3.43500 |
| 1212 | Zona Norte | 1 | 5 | 260 | 90 | 1 | 2 | 3 | Apartamento | acopi | -76.51350 | 3.45891 |
| 1724 | Zona Norte | 1 | 5 | 240 | 87 | 1 | 3 | 3 | Apartamento | acopi | -76.51700 | 3.36971 |
Acá se inicia asignando las variables de estrato, presio, area construida, parqueaderos, baños y habitaciones, además, se escalan para continuar con el proceso del PCA
# Selecciona las variables relevantes para el PCA
vivienda_pca <- vivienda2[, c("estrato", "preciom", "areaconst", "parqueaderos", "banios", "habitaciones")]
# Escala las variables para realizar el PCA
vivienda_pca_scaled <- scale(vivienda_pca)
# Realiza el PCA
res_pca <- prcomp(vivienda_pca_scaled)
# Aplicar PCA
pca_result <- prcomp(vivienda_pca_scaled, center = TRUE, scale. = TRUE)
vivienda3= vivienda2[4:9] %>%
scale()
head(vivienda3) # primeros 6 registros
estrato preciom areaconst parqueaderos banios habitaciones
1 -1.5872276 -0.5595498 -0.7339949 -0.3875522 -0.07793773 1.6406840
2 -1.5872276 -0.3465670 -0.3842568 -0.3875522 -0.77811479 -0.4147626
3 -1.5872276 -0.2552886 0.3152194 0.4168506 -0.77811479 0.2703863
4 -0.6156201 -0.1031580 0.7349051 1.2212534 1.32241640 -0.4147626
5 0.3559875 -0.5291236 -0.5940997 -0.3875522 -0.77811479 -0.4147626
6 0.3559875 -0.5899759 -0.6150839 -0.3875522 -0.07793773 -0.4147626
prcomp(vivienda3)
Standard deviations (1, .., p=6):
[1] 1.8480703 1.1222455 0.6779600 0.6592367 0.4909833 0.4357909
Rotation (n x k) = (6 x 6):
PC1 PC2 PC3 PC4 PC5 PC6
estrato 0.3306904 -0.5816950 0.5551021 0.07749341 0.46143880 -0.1587620
preciom 0.4781754 -0.1883533 -0.0359721 -0.36062553 -0.21967777 0.7458339
areaconst 0.4417250 0.2388377 -0.2878930 -0.61783592 0.27859384 -0.4534506
parqueaderos 0.4096354 -0.2607395 -0.6565763 0.57091588 0.04760414 -0.0700729
banios 0.4668745 0.1921461 0.3633148 0.18500105 -0.67876421 -0.3437503
habitaciones 0.2847775 0.6813261 0.2111757 0.34936005 0.44521273 0.2997240
vivienda3 = scale(vivienda2[,4:9])
res.pca <- prcomp(vivienda3)
fviz_eig(res.pca, addlabels = TRUE)
En este caso el primer componente principal explica el 56.9% de la variabilidad contenida en la base de datos y entre los 2 primeros se el 77.9% de los datos, lo cual indicaría que con dos variables (PC1, PC2) que se obtiene mediante una combinación lineal de las variables se puede resumir gran parte de la variabilidad que contiene la base de datos.
fviz_pca_var(res.pca,
col.var = "contrib", # Color by contributions to the PC
gradient.cols = c("#FF7F00", "#034D94"),
repel = TRUE # Avoid text overlapping
)
Al visualizar las variables en el plano de los componentes principales se identifica el sentido y la caracterización de los componentes. El primero componente principal está asociado principalmente con la variables habitaciones y área construida, mientras que el segundo componente se puede asociar a las variables estrato y precio.
Para explicar el sentido de los ejes, se escogen cuatro casos extremos conformados por las siguientes viviendas:
datos<- rbind(vivienda2[76,], # ok
vivienda2[4507,],
vivienda2[1360,],
vivienda2[15,])
datos <- as.data.frame(datos)
rownames(datos) = c("vivienda 76","vivienda 4507","vivienda 1360","vivienda 15")
datos
id zona piso estrato preciom areaconst parqueaderos
vivienda 76 2635 Zona Norte 0 5 420 105 0
vivienda 4507 5040 Zona Sur 3 3 420 360 1
vivienda 1360 6675 Zona Sur 1 6 1200 420 2
vivienda 15 7824 Zona Norte 2 4 600 160 1
banios habitaciones tipo barrio longitud latitud
vivienda 76 3 3 Apartamento acopi -76.52115 3.48967
vivienda 4507 4 8 Casa melendez -76.53464 3.44987
vivienda 1360 6 5 Casa ciudad jardín -76.54400 3.35700
vivienda 15 4 5 Casa acopi -76.55210 3.42125
casos1 <- rbind(res.pca$x[76,1:2],res.pca$x[4507,1:2]) # CP1
rownames(casos1) = c("76","4507")
casos1 <- as.data.frame(casos1)
casos2 <- rbind(res.pca$x[1360,1:2], res.pca$x[15,1:2]) # CP2
rownames(casos2) = c("1360","15")
casos2 <- as.data.frame(casos2)
fviz_pca_ind(res.pca, col.ind = "#DEDEDE", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07")) +
geom_point(data = casos1, aes(x = PC1, y = PC2), color = "red", size = 3) +
geom_point(data = casos2, aes(x = PC1, y = PC2), color = "blue", size = 3)
datos<- rbind(vivienda2[76,],
vivienda2[4507,],
vivienda2[1360,],
vivienda2[15,])
rownames(datos) = c("vivienda 76","vivienda 4507","vivienda 1360","vivienda 15")
datos
id zona piso estrato preciom areaconst parqueaderos
vivienda 76 2635 Zona Norte 0 5 420 105 0
vivienda 4507 5040 Zona Sur 3 3 420 360 1
vivienda 1360 6675 Zona Sur 1 6 1200 420 2
vivienda 15 7824 Zona Norte 2 4 600 160 1
banios habitaciones tipo barrio longitud latitud
vivienda 76 3 3 Apartamento acopi -76.52115 3.48967
vivienda 4507 4 8 Casa melendez -76.53464 3.44987
vivienda 1360 6 5 Casa ciudad jardín -76.54400 3.35700
vivienda 15 4 5 Casa acopi -76.55210 3.42125
En la vivienda 76 se observa que tiene 3 habitaciones y en comparación con la vivienda 4507 tiene 8 habitaciones, la cual se encuentra al extremo. Acá se observa como aumentan los valores en el primer componente. En comparación, observamos cómo la vivienda 4507 tiene más habitaciones, un estrato menor y un piso más alto en comparación con la vivienda 76. Además, al mencionar que el valor en el primer componente principal indica la posición en relación con los ingresos, podemos inferir que la vivienda 76 tiende a tener ingresos más bajos, mientras que la vivienda 4507 tiende a tener ingresos más altos.
La Vivienda 1360 se encuentra en la Zona Sur, tiene un estrato más alto (6), un piso más bajo (1), un precio por metro cuadrado más alto ($1200), un área construida de 420 metros cuadrados, 2 parqueaderos, 6 baños y 5 habitaciones.
En comparación, la Vivienda 15 está ubicada en la Zona Norte, tiene un estrato más bajo (4), un piso más alto (2), un precio por metro cuadrado más bajo ($600), un área construida de 600 metros cuadrados, 1 parqueadero, 4 baños y 5 habitaciones.
Ambas viviendas tienen características distintivas en términos de ubicación, estrato, precio, y distribución interna. La Vivienda 6675 destaca por su ubicación en la Zona Sur, estrato más alto y más baños, mientras que la Vivienda 15 tiene un área construida más grande y está ubicada en la Zona Norte.
Viviendacong = (vivienda2)
Viviendacong$piso <- as.numeric(Viviendacong$piso)
Para este análisis de conglomerados se seleccionan las varaibles estrato, precio, area construida, parqueaderos, baños, habitaciones y piso
# Seleccionar variables relevantes para el análisis de conglomerados
viviendacong1 <- select(Viviendacong, "estrato", "preciom", "areaconst", "parqueaderos", "banios", "habitaciones", "piso")
cor(viviendacong1)|>
round(2)
estrato preciom areaconst parqueaderos banios habitaciones piso
estrato 1.00 0.61 0.27 0.51 0.42 -0.07 0.11
preciom 0.61 1.00 0.69 0.64 0.67 0.26 -0.04
areaconst 0.27 0.69 1.00 0.48 0.65 0.52 -0.17
parqueaderos 0.51 0.64 0.48 1.00 0.52 0.20 0.02
banios 0.42 0.67 0.65 0.52 1.00 0.59 -0.08
habitaciones -0.07 0.26 0.52 0.20 0.59 1.00 -0.17
piso 0.11 -0.04 -0.17 0.02 -0.08 -0.17 1.00
Según la anterior matriz de correlación, se encuentran los siguientes resultados:
Correlación positiva (0.61): existe una asociación moderada positiva entre el estrato y el precio por metro cuadrado. Esto quiere decir que en general, propiedades en estratos más altos tienden a tener precios por metro cuadrado más altos.
Correlación positiva (0.69): hay una fuerte asociación positiva entre el precio por metro cuadrado y el área construida. Esto indica que a medida que aumenta el precio por metro cuadrado, también tiende a aumentar el área construida de las propiedades.
Correlación positiva (0.51): existe una asociación moderada positiva entre el estrato y el número de parqueaderos. Esto podría sugerir que propiedades en estratos más altos tienden a tener más parqueaderos.
Correlación positiva (0.59): hay una fuerte asociación positiva entre el número de baños y el número de habitaciones. Esto indica que las propiedades con más baños tienden a tener más habitaciones y viceversa.
Correlación positiva (0.52): existe una asociación moderada positiva entre el área construida y el número de habitaciones. Esto sugiere que propiedades con un área construida más grande tienden a tener más habitaciones.
Correlación negativa (-0.17): hay una asociación moderada negativa entre el número de habitaciones y el piso. Esto podría significar que propiedades con más habitaciones tienden a estar en pisos más bajos.
## Se estandarizar las variables para tener media 0 y varianza 1
viviendacong2 = scale(viviendacong1)
viviendacong2 = as.data.frame(viviendacong2)
fviz_nbclust(viviendacong2, kmeans, method = "wss")
fviz_nbclust(viviendacong2, kmeans, method = "silhouette")
Los anteriores gráficos sugieren que se utilicen 2 cluster para el análisis de los conglomerados
k2 <- kmeans(viviendacong2, centers = 2, nstart = 25)
fviz_cluster(k2, data = viviendacong2)
# distancia euclidiana
dist_vivi <- dist(viviendacong1, method = 'euclidean')
# Cluster jerarquico con el método complete
hc_emp <- hclust(dist_vivi, method = 'complete')
# Determinamos a dónde pertenece cada observación
cluster_assigments <- cutree(hc_emp, k = 2)
# asignamos los clusters
assigned_cluster <- viviendacong1 %>% mutate(cluster = as.factor(cluster_assigments))
# gráfico de puntos
ggplot(assigned_cluster, aes(x = estrato, y = areaconst, color = cluster)) +
geom_point(size = 2) +
geom_text(aes(label = cluster), vjust = -.8) + # Agregar etiquetas del clúster
theme_classic()
La formación de dos clusters distintos sugiere que hay diferencias significativas en las propiedades residenciales en términos de estrato socioeconómico y área construida. Este hallazgo indica la existencia de patrones claros.
También se observa que el cluster 1 Incluye propiedades con características específicas, como estrato bajo, áreas construidas más pequeñas, y un menor número de comodidades como parqueaderos y habitaciones. Y el cluster Caracterizado por propiedades de estratos más altos, áreas construidas más grandes, y comodidades adicionales Este cluster representa propiedades más espaciosas.
#```{r, echo=FALSE}
# distancia euclidiana
dist_vivi <- dist(viviendacong1, method = 'euclidean')
# Cluster jerarquico con el método complete
hc_emp <- hclust(dist_vivi, method = 'complete')
# Determinamos a dónde pertenece cada observación
cluster_assigments <- cutree(hc_emp, k = 2)
# Calcular el coeficiente de Silhouette
sil <- silhouette(cluster_assigments, dist(viviendacong1))
sil_avg <- mean(sil[,3])
# Imprimir el coeficiente de Silhouette promedio
cat("Coeficiente de Silhouette promedio k=2 : ", sil_avg)
Coeficiente de Silhouette promedio k=2 : 0.6931269
El Coeficiente de Silhouette promedio sugiere que la configuración de dos clústeres es apropiada y que las observaciones dentro de cada clúster están más cerca de las otras observaciones en el mismo clúster que de las observaciones en otros clústeres.
Acá se construye una tabla cruzada con las variables involucradas en el análisis :
Zona : Centro, Norte, Oeste, Oriente, Sur Estrato : 3,4,5,6
library(FactoMineR)
tabla <- table(vivienda2$zona, vivienda2$estrato)
colnames(tabla) <- c("Estrato3", "Estrato4", "Estrato5", "Estrato6" )
tabla
Estrato3 Estrato4 Estrato5 Estrato6
Zona Centro 105 14 4 1
Zona Norte 572 407 769 172
Zona Oeste 54 84 290 770
Zona Oriente 340 8 2 1
Zona Sur 382 1616 1685 1043
chisq.test(tabla)
Pearson's Chi-squared test
data: tabla
X-squared = 3830.4, df = 12, p-value < 2.2e-16
Dado que el p-valor es prácticamente cero (menor que cualquier nivel de significancia común, como 0.05), hay evidencia estadística suficiente para rechazar la hipótesis nula de independencia.
resultados_ac <- CA(tabla)
El gráfico permite establecer relaciones y validarlas como son:
El estrato 3 se encuentra en la Zona Oriente y Centro El estrato 6 se encuentra ubicado en la Zona Oeste Los estratos 4 y 5 están ubicados principalmente en la Zona Sur y en a zona Norte el estrato 5 es el único presente
valores_prop <-resultados_ac$eig ; valores_prop
eigenvalue percentage of variance cumulative percentage of variance
dim 1 0.32215213 69.965515 69.96551
dim 2 0.12745096 27.680002 97.64552
dim 3 0.01084108 2.354483 100.00000
En este resultado se sugiere que la dimensión 1 es la más relevante y explica la mayoría de la variabilidad.
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")
Los resultados indican que el primer componente resume el 70 % y los dos primeros componentes y los dos primeros ejes resumen un 97.7% de los datos.
Zona : Centro, Norte, Oeste, Oriente, Sur Tipo de vivienda : Casa, apartamento
tabla2 <- table(vivienda2$zona, vivienda2$tipo)
colnames(tabla2) <- c("Casa", "Apartamento")
tabla2
Casa Apartamento
Zona Centro 24 100
Zona Norte 1198 722
Zona Oeste 1029 169
Zona Oriente 62 289
Zona Sur 2787 1939
chisq.test(tabla2)
Pearson's Chi-squared test
data: tabla2
X-squared = 690.93, df = 4, p-value < 2.2e-16
En este análisis también se rechazar la hipótesis nula de independencia dado que el p-valor es prácticamente cero (menor que cualquier nivel de significancia común, como 0.05)
res.ACM <- MCA(vivienda2[,c(2,10)], graph = FALSE,)
fviz_mca_var(res.ACM, repel = TRUE, col.var = "blue")
El gráfico permite establecer relaciones y validarlas como son:
El tipo de vivienda Casa se encuentra en la Zona centro, sur y oroente
El tipo de vivienda apartamento se encuentra en la Zona norte y oeste.
valores_prop <-res.ACM$eig ; valores_prop
eigenvalue percentage of variance cumulative percentage of variance
dim 1 0.6440958 25.76383 25.76383
dim 2 0.5000000 20.00000 45.76383
dim 3 0.5000000 20.00000 65.76383
dim 4 0.5000000 20.00000 85.76383
dim 5 0.3559042 14.23617 100.00000
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")
Los resultados indican que el primer componente resume el 70 % y los dos primeros componentes y los dos primeros ejes resumen un 97.7% de los datos, igual que con las variables, zona y estrato.
El análisis detallado de los datos de vivienda revela información valiosa sobre las propiedades residenciales. A continuación, se presentan algunos hallazgos clave y conclusiones derivadas de los diferentes análisis realizados:
Recomendaciones: - Considerar estrategias de segmentación de mercado basadas en las diferencias observadas entre los clusters. - En el caso del análisis por correspondencia se puede hacer un zoom a los tipos de vivienda y el estrato, es interesante validar una de las estrategias sobre la ubicación de estratos específicos a los que se quieran llegar con alguna táctica de venta u oferta de compra de viviendas.