vivienda_num <- vivienda[, sapply(vivienda, is.numeric)]
vivienda_num <- na.omit(vivienda_num)
vivienda_scaled <- scale(vivienda_num)
pca_result <- prcomp(vivienda_scaled, center = TRUE, scale. = TRUE)
summary(pca_result)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## Standard deviation 1.9628 1.3725 1.0095 0.9673 0.69386 0.59741 0.49420
## Proportion of Variance 0.4281 0.2093 0.1132 0.1040 0.05349 0.03966 0.02714
## Cumulative Proportion 0.4281 0.6374 0.7506 0.8546 0.90804 0.94770 0.97483
## PC8 PC9
## Standard deviation 0.43328 0.19689
## Proportion of Variance 0.02086 0.00431
## Cumulative Proportion 0.99569 1.00000
library(ggplot2)
variance_explained <- pca_result$sdev^2 / sum(pca_result$sdev^2)
ggplot(data = data.frame(PC = 1:length(variance_explained), VarExp = variance_explained), aes(x = PC, y = VarExp)) +
geom_bar(stat = "identity", fill = "steelblue") +
geom_line(aes(y = cumsum(VarExp)), color = "red", linetype = "dashed") +
labs(title = "Varianza Explicada por Componentes Principales", x = "Componente Principal", y = "Proporción de Varianza Explicada") +
theme_minimal()
### 1.6 Se visualizan las observaciones en los primeros componentes
library(ggplot2)
pc_data <- as.data.frame(pca_result$x)
ggplot(pc_data, aes(x = PC1, y = PC2)) +
geom_point(alpha = 0.5, color = "blue") +
labs(title = "PCA: Primeros 2 Componentes", x = "PC1", y = "PC2") +
theme_minimal()
### 1.7 Se utiliza Biplot para observar la relación entre variables y
componentes
library(ggbiplot)
## Warning: package 'ggbiplot' was built under R version 4.4.2
ggbiplot(pca_result, labels = rownames(pca_result$x), ellipse = TRUE)
###2.1 Cargar y preparar los datos - Asegurar que los datos estén bien estructurados y solo contienen variables numéricas:
library(paqueteMODELOS)
data("vivienda")
str(vivienda) # Ver estructura
## 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")=List of 3
## ..$ cols :List of 13
## .. ..$ id : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ zona : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ piso : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ estrato : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ preciom : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ areaconst : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ parqueaderos: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ banios : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ habitaciones: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ tipo : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ barrio : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ longitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ latitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## ..$ default: list()
## .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
## ..$ delim : chr ";"
## ..- attr(*, "class")= chr "col_spec"
## - attr(*, "problems")=<externalptr>
# 1. Eliminar la columna id
vivienda <- vivienda[, !names(vivienda) %in% "id"]
# 2. Seleccionar solo variables numéricas (sin id)
vivienda_num <- vivienda[, sapply(vivienda, is.numeric)]
# 3. Filtrar filas sin NA
vivienda_num <- na.omit(vivienda_num)
# 4. Estandarizar los datos
vivienda_scaled <- scale(vivienda_num)
# 5. Aplicar K-means
set.seed(123)
k_optimo <- 4 # Cambia esto según el método del codo
kmeans_result <- kmeans(vivienda_scaled, centers = k_optimo, nstart = 25)
###2.2 Determinar el número óptimo de clusters (K), usando el Elbow Method
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.4.2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(factoextra)
# Calcular la suma de cuadrados dentro de los grupos (WSS) para diferentes valores de k
fviz_nbclust(vivienda_scaled, kmeans, method = "wss") +
labs(title = "Método del Codo para Seleccionar K")
###Ahora utilizando el método de la silueta:
fviz_nbclust(vivienda_scaled, kmeans, method = "silhouette") +
labs(title = "Método de la Silueta para Seleccionar K")
### 2.3 Aplicar K-means para segmentar propiedades
# Verificar la cantidad de filas
nrow(vivienda) # Número original de filas
## [1] 8322
nrow(vivienda_scaled) # Número de filas después de eliminar NA
## [1] 6717
# 1. Filtrar datos antes de todo
vivienda <- vivienda[complete.cases(vivienda), ]
# 2. Seleccionar solo variables numéricas
vivienda_num <- vivienda[, sapply(vivienda, is.numeric)]
# 3. Estandarizar los datos
vivienda_scaled <- scale(vivienda_num)
# 4. Aplicar K-means
set.seed(123)
kmeans_result <- kmeans(vivienda_scaled, centers = 4, nstart = 25)
# 5. Agregar clusters sin error
vivienda$cluster <- as.factor(kmeans_result$cluster)
set.seed(123) # Fijamos la semilla para reproducibilidad
k_optimo <- 4 # Ajusta este valor según el método del codo
# Aplicar K-Means
kmeans_result <- kmeans(vivienda_scaled, centers = k_optimo, nstart = 25)
# Agregar los clusters a la base original
vivienda$cluster <- as.factor(kmeans_result$cluster)
# Ver la distribución de los clusters
table(vivienda$cluster)
##
## 1 2 3 4
## 933 1868 591 1416
fviz_cluster(kmeans_result, data = vivienda_scaled, geom = "point",
ellipse.type = "convex", repel = TRUE) +
labs(title = "Segmentación de Propiedades Residenciales")
library(ggplot2)
ggplot(vivienda, aes(x = longitud, y = latitud, color = cluster)) +
geom_point(alpha = 0.5) +
labs(title = "Clusters de Propiedades en la Ciudad",
x = "Longitud", y = "Latitud") +
theme_minimal()
### 2.5 Se analizan las características que predominan en cada
cluster:
aggregate(vivienda_num, by = list(Cluster = vivienda$cluster), mean)
## Cluster estrato preciom areaconst parqueaderos banios habitaciones
## 1 1 4.152197 289.1951 133.19323 1.322615 2.630225 3.617363
## 2 2 4.460385 259.4754 97.09707 1.224839 2.348501 2.957709
## 3 3 5.450085 1029.3333 435.57545 3.719120 5.411168 5.201354
## 4 4 5.532486 589.9061 195.74824 2.123588 3.841102 3.646893
## longitud latitud
## 1 -76.51150 3.464985
## 2 -76.53150 3.393405
## 3 -76.53534 3.400288
## 4 -76.54012 3.413250
colnames(vivienda) # Muestra los nombres de las columnas
## [1] "zona" "piso" "estrato" "preciom" "areaconst"
## [6] "parqueaderos" "banios" "habitaciones" "tipo" "barrio"
## [11] "longitud" "latitud" "cluster"
library("FactoMineR")
## Warning: package 'FactoMineR' was built under R version 4.4.2
library("factoextra")
# Crear tabla de contingencia (combinando zona, tipo y barrio)
tabla_contingencia <- table(vivienda$zona, vivienda$tipo, vivienda$estrato)
# Ver la tabla generada
tabla_contingencia
## , , = 3
##
##
## Apartamento Casa
## Zona Centro 2 31
## Zona Norte 107 34
## Zona Oeste 10 9
## Zona Oriente 15 79
## Zona Sur 79 68
##
## , , = 4
##
##
## Apartamento Casa
## Zona Centro 2 1
## Zona Norte 114 70
## Zona Oeste 34 17
## Zona Oriente 1 1
## Zona Sur 657 316
##
## , , = 5
##
##
## Apartamento Casa
## Zona Centro 0 0
## Zona Norte 348 134
## Zona Oeste 153 28
## Zona Oriente 1 0
## Zona Sur 784 411
##
## , , = 6
##
##
## Apartamento Casa
## Zona Centro 0 0
## Zona Norte 63 16
## Zona Oeste 472 30
## Zona Oriente 0 0
## Zona Sur 340 381
# Asegúrate de que las variables sean de tipo factor
vivienda$zona <- as.factor(vivienda$zona)
vivienda$tipo <- as.factor(vivienda$tipo)
vivienda$estrato <- as.factor(vivienda$estrato)
# Seleccionar las columnas categóricas para el MCA
datos_mca <- vivienda[, c("zona", "tipo", "estrato")]
# Realizar el Análisis de Correspondencias Múltiples (MCA)
resultado_mca <- MCA(datos_mca, graph = FALSE)
# Resumen de los resultados
summary(resultado_mca)
##
## Call:
## MCA(X = datos_mca, graph = FALSE)
##
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3 Dim.4 Dim.5 Dim.6 Dim.7
## Variance 0.542 0.459 0.399 0.333 0.319 0.268 0.198
## % of var. 20.312 17.229 14.950 12.501 11.958 10.047 7.410
## Cumulative % of var. 20.312 37.541 52.491 64.993 76.950 86.997 94.407
## Dim.8
## Variance 0.149
## % of var. 5.593
## Cumulative % of var. 100.000
##
## Individuals (the 10 first)
## Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3 ctr
## 1 | 0.243 0.002 0.032 | -0.653 0.019 0.232 | -0.974 0.049
## 2 | -0.037 0.000 0.001 | -0.413 0.008 0.078 | 1.350 0.095
## 3 | -0.037 0.000 0.001 | -0.413 0.008 0.078 | 1.350 0.095
## 4 | -0.003 0.000 0.000 | -0.554 0.014 0.117 | 0.593 0.018
## 5 | -0.037 0.000 0.001 | -0.413 0.008 0.078 | 1.350 0.095
## 6 | 0.398 0.006 0.060 | -0.532 0.013 0.106 | 0.857 0.038
## 7 | 0.398 0.006 0.060 | -0.532 0.013 0.106 | 0.857 0.038
## 8 | 0.432 0.007 0.060 | -0.673 0.021 0.145 | 0.099 0.001
## 9 | 0.398 0.006 0.060 | -0.532 0.013 0.106 | 0.857 0.038
## 10 | -0.275 0.003 0.030 | 0.371 0.006 0.054 | 0.745 0.029
## cos2
## 1 0.517 |
## 2 0.839 |
## 3 0.839 |
## 4 0.134 |
## 5 0.839 |
## 6 0.276 |
## 7 0.276 |
## 8 0.003 |
## 9 0.276 |
## 10 0.218 |
##
## Categories (the 10 first)
## Dim.1 ctr cos2 v.test Dim.2 ctr cos2
## Zona Centro | 4.479 9.244 0.151 26.973 | 1.873 1.905 0.026
## Zona Norte | 0.354 1.421 0.028 11.667 | -0.429 2.457 0.042
## Zona Oeste | -0.973 9.116 0.176 -29.057 | 1.698 32.758 0.535
## Zona Oriente | 4.590 26.162 0.434 45.668 | 2.167 6.872 0.097
## Zona Sur | -0.062 0.149 0.007 -5.615 | -0.387 6.878 0.257
## Apartamento | -0.324 4.284 0.206 -31.457 | 0.082 0.321 0.013
## Casa | 0.635 8.384 0.206 31.457 | -0.160 0.627 0.013
## 3 | 2.481 34.185 0.611 54.177 | 0.989 6.407 0.097
## 4 | -0.036 0.020 0.000 -1.437 | -0.780 11.143 0.205
## 5 | -0.110 0.289 0.008 -6.072 | -0.493 6.816 0.153
## v.test Dim.3 ctr cos2 v.test
## Zona Centro 11.278 | -0.856 0.459 0.006 -5.157 |
## Zona Norte -14.126 | 1.547 36.870 0.541 50.977 |
## Zona Oeste 50.730 | 0.200 0.524 0.007 5.976 |
## Zona Oriente 21.556 | -0.158 0.042 0.001 -1.570 |
## Zona Sur -35.164 | -0.486 12.463 0.404 -44.092 |
## Apartamento 7.925 | 0.316 5.540 0.196 30.688 |
## Casa -7.925 | -0.619 10.841 0.196 -30.688 |
## 3 21.601 | 0.446 1.502 0.020 9.744 |
## 4 -31.423 | -0.740 11.543 0.185 -29.792 |
## 5 -27.134 | 0.695 15.602 0.304 38.242 |
##
## Categorical variables (eta2)
## Dim.1 Dim.2 Dim.3
## zona | 0.749 0.701 0.602 |
## tipo | 0.206 0.013 0.196 |
## estrato | 0.670 0.664 0.398 |
# Actualizar el paquete grDevices
update.packages("grDevices")
fviz_mca_biplot(resultado_mca, repel = TRUE)
# Cargar librerías necesarias
library(FactoMineR) # Para el análisis MCA
library(factoextra) # Para visualizaciones elegantes
library(ggplot2) # Para gráficos personalizados
library(dplyr) # Para manipulación de datos
##
## Adjuntando el paquete: 'dplyr'
## The following object is masked from 'package:gridExtra':
##
## combine
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# Asegurarse de que las variables sean de tipo factor
vivienda$zona <- as.factor(vivienda$zona)
vivienda$tipo <- as.factor(vivienda$tipo)
vivienda$estrato <- as.factor(vivienda$estrato)
# Seleccionar las columnas categóricas para el MCA
datos_mca <- vivienda[, c("zona", "tipo", "estrato")]
# Realizar el Análisis de Correspondencias Múltiples (MCA)
resultado_mca <- MCA(datos_mca, graph = FALSE)
# Resumen de los resultados
summary(resultado_mca)
##
## Call:
## MCA(X = datos_mca, graph = FALSE)
##
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3 Dim.4 Dim.5 Dim.6 Dim.7
## Variance 0.542 0.459 0.399 0.333 0.319 0.268 0.198
## % of var. 20.312 17.229 14.950 12.501 11.958 10.047 7.410
## Cumulative % of var. 20.312 37.541 52.491 64.993 76.950 86.997 94.407
## Dim.8
## Variance 0.149
## % of var. 5.593
## Cumulative % of var. 100.000
##
## Individuals (the 10 first)
## Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3 ctr
## 1 | 0.243 0.002 0.032 | -0.653 0.019 0.232 | -0.974 0.049
## 2 | -0.037 0.000 0.001 | -0.413 0.008 0.078 | 1.350 0.095
## 3 | -0.037 0.000 0.001 | -0.413 0.008 0.078 | 1.350 0.095
## 4 | -0.003 0.000 0.000 | -0.554 0.014 0.117 | 0.593 0.018
## 5 | -0.037 0.000 0.001 | -0.413 0.008 0.078 | 1.350 0.095
## 6 | 0.398 0.006 0.060 | -0.532 0.013 0.106 | 0.857 0.038
## 7 | 0.398 0.006 0.060 | -0.532 0.013 0.106 | 0.857 0.038
## 8 | 0.432 0.007 0.060 | -0.673 0.021 0.145 | 0.099 0.001
## 9 | 0.398 0.006 0.060 | -0.532 0.013 0.106 | 0.857 0.038
## 10 | -0.275 0.003 0.030 | 0.371 0.006 0.054 | 0.745 0.029
## cos2
## 1 0.517 |
## 2 0.839 |
## 3 0.839 |
## 4 0.134 |
## 5 0.839 |
## 6 0.276 |
## 7 0.276 |
## 8 0.003 |
## 9 0.276 |
## 10 0.218 |
##
## Categories (the 10 first)
## Dim.1 ctr cos2 v.test Dim.2 ctr cos2
## Zona Centro | 4.479 9.244 0.151 26.973 | 1.873 1.905 0.026
## Zona Norte | 0.354 1.421 0.028 11.667 | -0.429 2.457 0.042
## Zona Oeste | -0.973 9.116 0.176 -29.057 | 1.698 32.758 0.535
## Zona Oriente | 4.590 26.162 0.434 45.668 | 2.167 6.872 0.097
## Zona Sur | -0.062 0.149 0.007 -5.615 | -0.387 6.878 0.257
## Apartamento | -0.324 4.284 0.206 -31.457 | 0.082 0.321 0.013
## Casa | 0.635 8.384 0.206 31.457 | -0.160 0.627 0.013
## 3 | 2.481 34.185 0.611 54.177 | 0.989 6.407 0.097
## 4 | -0.036 0.020 0.000 -1.437 | -0.780 11.143 0.205
## 5 | -0.110 0.289 0.008 -6.072 | -0.493 6.816 0.153
## v.test Dim.3 ctr cos2 v.test
## Zona Centro 11.278 | -0.856 0.459 0.006 -5.157 |
## Zona Norte -14.126 | 1.547 36.870 0.541 50.977 |
## Zona Oeste 50.730 | 0.200 0.524 0.007 5.976 |
## Zona Oriente 21.556 | -0.158 0.042 0.001 -1.570 |
## Zona Sur -35.164 | -0.486 12.463 0.404 -44.092 |
## Apartamento 7.925 | 0.316 5.540 0.196 30.688 |
## Casa -7.925 | -0.619 10.841 0.196 -30.688 |
## 3 21.601 | 0.446 1.502 0.020 9.744 |
## 4 -31.423 | -0.740 11.543 0.185 -29.792 |
## 5 -27.134 | 0.695 15.602 0.304 38.242 |
##
## Categorical variables (eta2)
## Dim.1 Dim.2 Dim.3
## zona | 0.749 0.701 0.602 |
## tipo | 0.206 0.013 0.196 |
## estrato | 0.670 0.664 0.398 |
# Visualización 1: Gráfico de variables (categorías)
fviz_mca_var(resultado_mca, repel = TRUE) +
ggtitle("Gráfico de Categorías (MCA)") +
theme_minimal()
# Visualización 2: Gráfico de individuos (casos)
fviz_mca_ind(resultado_mca, repel = TRUE) +
ggtitle("Gráfico de Individuos (MCA)") +
theme_minimal()
# Visualización 3: Biplot (individuos y variables)
fviz_mca_biplot(resultado_mca, repel = TRUE) +
ggtitle("Biplot de Individuos y Categorías (MCA)") +
theme_minimal()
# Visualización 4: Mapa de calor de contribuciones
fviz_contrib(resultado_mca, choice = "var", axes = 1:2, top = 15) +
ggtitle("Contribución de Categorías a las Dimensiones") +
theme_minimal()
# Visualización 5: Gráfico de barras de estratos por zona
ggplot(vivienda, aes(x = zona, fill = estrato)) +
geom_bar(position = "fill") +
labs(title = "Distribución de Estratos por Zona",
x = "Zona",
y = "Proporción",
fill = "Estrato") +
theme_minimal()
# Visualización 6: Gráfico de barras de tipos por estrato
ggplot(vivienda, aes(x = tipo, fill = estrato)) +
geom_bar(position = "fill") +
labs(title = "Distribución de Tipos por Estrato",
x = "Tipo",
y = "Proporción",
fill = "Estrato") +
theme_minimal()
# Con base en estos resultados se pueden hacer las siguientes
observaciones:
Dado que la variable “zona” es la más influyente en las dimensiones 1 y 2, se determina que la ubicación geográfica es un factor diferencial relevante, esto lo corrobora el predominio de estrato 3 en las zonas centro y oriente, con unos precios por metro cuadrado más bajos que en otras zonas.
Otra variable que tiene una alta contribución en las dimensiones 1 y 2 es el estrato, por lo que se puede determinar que hay patrones claramente definidos entre las zonas y las clases sociales.
Dado que el tipo de vivienda tiene un menor impacto, sobretodo en la dimensión 2, de puede determinar que si el inmueble es casa o apartamento no es un factor diferenciador (se tiene en cuenta el número de metros cuadrados más que el tipo de propiedad).
Teniendo en cuenta lo anterior se hacen las siguientes recomendaciones a la inmobiliaria:
Manejar la venta de predios de estrato 3 (cluster 1) como un negocio de volumen, por la gran cantidad de inmuebles y su precio bajo, es decir un menor margen que puede ser compensado por la cantidad de casas y apartamentos que comercialice en esta zonas. Puede designar a un equipo comercial que se dedique exclusivamente a la venta de estos inmuebles, con una meta (en cantidad) superior a los asesores que se dediquen a otras zonas y un perfil diferente. Adicional a lo anterior, dado que las casas de estrato 3 tienen un menor precio por metro cuadrado respecto a otras zonas y tienen un área considerable, le ofrecería a los inversionistas, la opción de comprar estas casas como lotes de bajo precio para construir edificios y multiplicar el número de metros cuadrados para vender en el mercado.
La venta de los predios que pertenecen al cluster 3, es decir, que se encuentran en estrato 5 y 6, que tienen aréas construidas considerables, con un gran número de habitaciones y baños, debería manejarse como un negocio de margen, por lo que pueden designar pocos asesores comerciales a esta zona, que en una sola venta, comisionen lo que los asesores del cluster 1 hacen en 3 o 4 ventas, por supuesto su meta comercial sería menor en cantidad o podría medirse por precio de venta o valor facturado.
La fuerza comercial que se dedique a los predios del cluster 2 y 4, debe tener en cuenta 2 nichos de mercado, el de los espacios aspiracionales (estrato 4-5) con menor cantidad de baños y habitaciones, es decir, parejas sin hijos y personas que vivan solas y el de las familias pequeñas que prefieran vivir en estrato 5-6 en un área construida un poco más grande. Este segmento no se puede descuidar para no permitirle a la competencia que gane espacio en este tipo de predios.
El flujo de caja de la inmobiliaria debería estar concentrado en los predios del cluster 1 y los ingresos por márgenes superiores, en los inmuebles del cluster 3.