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.
En el siguiente informe busca responder a las necesidades de la empresa inmobiliaria tras realizar un análisis integral y multidimensional de la base de datos para obtener una comprensión del mercado inmobiliario urbano. Para ello, se aplican diversas técnicas de análisis de datos, incluyendo: Análisis de componentes Principales, Análisis de Conglomerados y Análisis de Correspondencia. Sin embargo, se inicia realizando un EDA (Análisis Exploratorio de Datos) para el entendimiento de los datos.
A partir de una exploración inicial de los datos se identifica un conjunto de datos de vienda conformado por 8.322 observaciones que cuentan con 13 variables que incluyen 4 variables categóricas: “zona”,“tipo”, “estrato” y “barrio”, y 9 variables numéricas, sin tener en cuenta el identificador (id): “piso”, “estrato”, “preciom”, “areaconst”,“parquea”, “banios”, “habitac”, “longitud” y “latitud”. Se identificaron los datos faltantes para cada una de las variables concluyendo que solo hay vacíos en las columnas “parque” y “piso”. Adicionalmente, se identifica la necesidad de transformar la variable piso originalmente almacenada como tipo String a un Entero.
#Carga de los datos de Vivienda
data("vivienda")
head(vivienda,5)
# A tibble: 5 × 13
id zona piso estrato preciom areaconst parqueaderos banios habitaciones
<dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1147 Zona O… <NA> 3 250 70 1 3 6
2 1169 Zona O… <NA> 3 320 120 1 2 3
3 1350 Zona O… <NA> 3 350 220 2 2 4
4 5992 Zona S… 02 4 400 280 3 5 3
5 1212 Zona N… 01 5 260 90 1 2 3
# ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
#Exploración inicial de las variables y sus tipos
glimpse(vivienda)
Rows: 8,322
Columns: 13
$ id <dbl> 1147, 1169, 1350, 5992, 1212, 1724, 2326, 4386, 1209, 159…
$ zona <chr> "Zona Oriente", "Zona Oriente", "Zona Oriente", "Zona Sur…
$ piso <chr> NA, NA, NA, "02", "01", "01", "01", "01", "02", "02", "02…
$ estrato <dbl> 3, 3, 3, 4, 5, 5, 4, 5, 5, 5, 6, 4, 5, 6, 4, 5, 5, 4, 5, …
$ preciom <dbl> 250, 320, 350, 400, 260, 240, 220, 310, 320, 780, 750, 62…
$ areaconst <dbl> 70, 120, 220, 280, 90, 87, 52, 137, 150, 380, 445, 355, 2…
$ parqueaderos <dbl> 1, 1, 2, 3, 1, 1, 2, 2, 2, 2, NA, 3, 2, 2, 1, 4, 2, 2, 2,…
$ banios <dbl> 3, 2, 2, 5, 2, 3, 2, 3, 4, 3, 7, 5, 6, 2, 4, 4, 4, 3, 2, …
$ habitaciones <dbl> 6, 3, 4, 3, 3, 3, 3, 4, 6, 3, 6, 5, 6, 2, 5, 5, 4, 3, 3, …
$ tipo <chr> "Casa", "Casa", "Casa", "Casa", "Apartamento", "Apartamen…
$ barrio <chr> "20 de julio", "20 de julio", "20 de julio", "3 de julio"…
$ longitud <dbl> -76.51168, -76.51237, -76.51537, -76.54000, -76.51350, -7…
$ latitud <dbl> 3.43382, 3.43369, 3.43566, 3.43500, 3.45891, 3.36971, 3.4…
Se realiza un análisis exploratorio de sus medidas de tendencia central y distribución.
# Resumen con mejor formato
skim(vivienda)
Name | vivienda |
Number of rows | 8322 |
Number of columns | 13 |
_______________________ | |
Column type frequency: | |
character | 4 |
numeric | 9 |
________________________ | |
Group variables | None |
Variable type: character
skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
---|---|---|---|---|---|---|---|
zona | 3 | 1.00 | 8 | 12 | 0 | 5 | 0 |
piso | 2638 | 0.68 | 2 | 2 | 0 | 12 | 0 |
tipo | 3 | 1.00 | 4 | 11 | 0 | 2 | 0 |
barrio | 3 | 1.00 | 4 | 29 | 0 | 436 | 0 |
Variable type: numeric
skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
---|---|---|---|---|---|---|---|---|---|---|
id | 3 | 1.00 | 4160.00 | 2401.63 | 1.00 | 2080.50 | 4160.00 | 6239.50 | 8319.00 | ▇▇▇▇▇ |
estrato | 3 | 1.00 | 4.63 | 1.03 | 3.00 | 4.00 | 5.00 | 5.00 | 6.00 | ▅▆▁▇▆ |
preciom | 2 | 1.00 | 433.89 | 328.65 | 58.00 | 220.00 | 330.00 | 540.00 | 1999.00 | ▇▂▁▁▁ |
areaconst | 3 | 1.00 | 174.93 | 142.96 | 30.00 | 80.00 | 123.00 | 229.00 | 1745.00 | ▇▁▁▁▁ |
parqueaderos | 1605 | 0.81 | 1.84 | 1.12 | 1.00 | 1.00 | 2.00 | 2.00 | 10.00 | ▇▁▁▁▁ |
banios | 3 | 1.00 | 3.11 | 1.43 | 0.00 | 2.00 | 3.00 | 4.00 | 10.00 | ▇▇▃▁▁ |
habitaciones | 3 | 1.00 | 3.61 | 1.46 | 0.00 | 3.00 | 3.00 | 4.00 | 10.00 | ▂▇▂▁▁ |
longitud | 3 | 1.00 | -76.53 | 0.02 | -76.59 | -76.54 | -76.53 | -76.52 | -76.46 | ▁▅▇▂▁ |
latitud | 3 | 1.00 | 3.42 | 0.04 | 3.33 | 3.38 | 3.42 | 3.45 | 3.50 | ▃▇▅▇▅ |
Para la variable parquea (Parqueadero), se asume que los 1.606 datos faltantes corresponden a viviendas sin parqueadero, por lo que se ajusta el valor faltante a 0.
0 1 2 3 4 5 6 7 8 9 10
1605 3155 2475 520 384 68 68 18 17 4 8
En el caso de los 2.638 datos faltantes en la variable piso, los datos faltantes corresponden a aquellos donde el tipo de vivienda es “CASA”, que es una variable que reporta la ubicación de los “APARTAMENTOS” en el edificio. Se ajusta entonces eliminando los valores de piso cuando tipo es igual a “CASA”.
Al no identificar un patrón lógico para los valores vacíos de la columna piso, como que estén vacíos por corresponder a la variable Casa, se opta por eliminar los registros vacíos del dataset.
# Eliminar filas con NA
vivienda$piso <- as.integer(vivienda$piso)
vivienda_clean <- drop_na(vivienda)
# Ver el dataframe limpio
print(vivienda_clean)
# A tibble: 5,684 × 13
id zona piso estrato preciom areaconst parqueaderos banios habitaciones
<dbl> <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 5992 Zona … 2 4 400 280 3 5 3
2 1212 Zona … 1 5 260 90 1 2 3
3 1724 Zona … 1 5 240 87 1 3 3
4 2326 Zona … 1 4 220 52 2 2 3
5 4386 Zona … 1 5 310 137 2 3 4
6 1209 Zona … 2 5 320 150 2 4 6
7 1592 Zona … 2 5 780 380 2 3 3
8 4057 Zona … 2 6 750 445 0 7 6
9 4460 Zona … 2 4 625 355 3 5 5
10 6081 Zona … 2 5 750 237 2 6 6
# ℹ 5,674 more rows
# ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
#Inicialmente revisemos si existen datos faltantes
md.pattern(vivienda_clean, 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
5684 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0
tipo barrio longitud latitud
5684 1 1 1 1 0
0 0 0 0 0
#Análisis de Componentes Principales
#Generar un subset solo para las variables numéricas
vivienda_num <- vivienda_clean[, c("piso", "preciom", "areaconst","parqueaderos", "banios", "habitaciones")]
vivienda_z <- scale(vivienda_num)
vivienda_pca <- prcomp(vivienda_z)
fviz_eig(vivienda_pca, addlabels = TRUE)
En este caso el primer componente principal explica el 54.8% de la
variabilidad contenida en las variables numéricas del DataFrame
Vivienda. Entre los tres primeros compononetes se explica cerca del 85%
de la variabilidad (79.8). Sien embarco la gráfica indica que con solo
una variable (CP1) 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.
# Definir el número de componentes a visualizar
components <- list(c(1, 2), c(1, 3), c(2, 3))
# Crear una lista para almacenar los gráficos
plot_list <- list()
# Generar las gráficas de las variables para cada par de componentes
for (i in seq_along(components)) {
pc <- components[[i]]
p <- fviz_pca_var(vivienda_pca,
axes = pc, # Ejes correspondientes (PC1-PC2, PC1-PC3, PC2-PC3)
col.var = "contrib",
gradient.cols = c("blue", "red"),
repel = TRUE) +
ggtitle(paste("Variables en PC", pc[1], "vs PC", pc[2])) # Título dinámico
plot_list[[i]] <- p
}
# Organizar los gráficos en un mosaico de 2 filas y 2 columnas
grid.arrange(grobs = plot_list, ncol = 2)
En el componente 1 las variables preciom, banios y areaconst tienen
vectores largos y apuntan en la misma dirección, lo que significa que
están altamente correlacionadas (viviendas más grandes y con más
habitaciones y baños tienden a ser más costosas). Ya que la variable
piso está orientado en otra dirección casi perpendicular a preciom,
indicaría que la altura del piso no está directamente relacionada con el
tamaño/precio, sino que puede reflejar otro factor como la ubicación.
habitaciones y parqueaderos tienen vecotres un poco más dispersos y su
contribución es relativamente menor, así que al igual que piso también
pueden estar más relacionadas con la ubicación, aunque aportan en mayor
medida a explicar la variabilidad del componente.
En el siguiente gráfico aplicado sobre los primeros 3 componentes podemos observar como aporta cada variable en cada componente.
# Definir el número de componentes principales que quieres visualizar
n_components <- 3 # Puedes ajustar este número según tus necesidades
# Crear una lista para almacenar los gráficos
plot_list <- list()
# Generar las gráficas de contribución para cada componente principal
for (i in 1:n_components) {
# Crear el gráfico de contribución para el componente i
p <- fviz_contrib(vivienda_pca, choice = "var", axes = i, top = 10)
# Agregar el gráfico a la lista
plot_list[[paste0("PC", i)]] <- p
}
# Organizar los gráficos en un mosaico
grid.arrange(grobs = plot_list, ncol = 3) # Ajusta ncol según el número de gráficos que quieras por fila
El resultado indica que en el primer componente (CP1) el número de baños, el área construida y el precio estan correlacionadas, haciendo que este componente represente el tamaño y valor de la vivienda. Por otro lado el hecho de que banios (baños) y parqueaderos tengan contribuciones altas pueden reflejar un favor de comodidad que afecta el precio.
En el segundo componente piso, habitaciones y parqueaderos tienen alta contribución lo que puede estar reflejando un factor de ubicación o accesibilidad.
En el componente 3 habitaciones y piso son la variables dominantes sugireindoque este representa una variabilidad independiente del tamaño o el precio. Esto suele ser raro para el número de habitaciones. Lo que quizás este mostrando un factor asociado nuevamente a la ubicación o sector de ubicación de la vivienda que afecta este resultado.
En este último gráfico es una visualización de los individuos (observaciones) en el Análisis de Componentes Principales (PCA). En estos casos los puntos están dispersos a lo largo de un eje, explicando que ese componente principal (CP1) es clave para explicar la variabilidad de los datos. No se observa que los puntos formen grupos o clústeres, por lo que se puede presumir que no hay estructuras o patrones en los datos (como diferentes categorías o clasificaciones). Excepto en la comparación del componente 2 y 3 donde si se ve una estructura
# Definir el número de dimensiones que quieres visualizar
n_dim <- 3 # Puedes ajustar este número según tus necesidades
# Crear una lista para almacenar los gráficos
plot_list <- list()
# Generar todas las combinaciones de dimensiones
for (i in 1:(n_dim - 1)) {
for (j in (i + 1):n_dim) {
# Crear el gráfico para la combinación de dimensiones i y j
p <- fviz_pca_ind(vivienda_pca, geom.ind = "point",
col.ind = "#FF7256",
axes = c(i, j),
pointsize = 1)
# Agregar el gráfico a la lista
plot_list[[paste0("Dim", i, "vsDim", j)]] <- p
}
}
# Organizar los gráficos en un mosaico
grid.arrange(grobs = plot_list, ncol = 2) # Ajusta ncol según el número de gráficos que quieras por fila
El análisis de conglomerados, también conocido como clustering, es un método estadístico usado para agrupar objetos similares en función de sus características. Mediante este análisis se logra identificar grupos muy parecidos (homogéneos) de objetos o individuos. En este caso se analizará si es posible generar agrupaciones de los datos del dataset de “vivivenda” a partir de sus variables.
En este método jerárquico se construye un dendograma en el cual se forman los grupos de individuos más parecidos, esto permite determinar el número de clases que se usarán en el método no jerárquico
Se cargan los datos originales transformados nuevamente para hacer el respectivo análisis de clusters.
vivienda_c<-vivienda_clean[,c("zona", "estrato", "preciom", "areaconst", "habitaciones", "banios", "tipo", "parqueaderos", "piso")]
# Definir las columnas a transformar
cols <- c("zona", "tipo")
# Convertir solo las columnas especificadas a factores y luego a números
vivienda_c[cols] <- lapply(vivienda_c[cols], function(x) as.numeric(as.factor(x)))
# Escalar las variables numéricas para evitar sesgos en el análisis de clusters
vivienda_scale <- scale(vivienda_c)
vivienda_scale = as.data.frame(vivienda_scale)
Los métodos Ward y Complete son dos enfoques comunes para la agrupación jerárquica en clustering jerárquico. Se decidió probar los dos debido a sus características y a que usando el método complete solo se lograba obtener un k=2. El Método Ward busca minimizar la variabilidad interna dentro de los clusters para datos con estructura clara y sin mucho ruido. Por otro lado el Método Complete se usa cuando se quiere enfatizar la separación entre clusters o si los datos contienen grupos bien diferenciados, lo que no parece ser el caso en este dataset..
A continuación se muestran los resultados del índice de Silhouette para cada método con un k de 2 a 10 .
library(cluster) # Para calcular el índice de Silhouette
library(dplyr) # Para manipulación de datos
# 1. Calcular la distancia euclidiana
dist_viv <- dist(vivienda_scale, method = "euclidean")
# 2. Aplicar el clustering jerárquico con métodos 'ward.D' y 'complete'
hc_ward <- hclust(dist_viv, method = "ward.D")
hc_complete <- hclust(dist_viv, method = "complete")
# 3. Crear un dataframe vacío para almacenar los resultados
silhouette_results <- data.frame(k = integer(), Complete = numeric(), Ward = numeric())
# 4. Ejecutar el ciclo for para probar de 2 a 10 clusters en ambos métodos
for (k in 2:10) {
# Asignar clusters para Complete
cluster_complete <- cutree(hc_complete, k = k)
silhouette_complete <- silhouette(cluster_complete, dist_viv)
silhouette_avg_complete <- mean(silhouette_complete[, 3])
# Asignar clusters para Ward
cluster_ward <- cutree(hc_ward, k = k)
silhouette_ward <- silhouette(cluster_ward, dist_viv)
silhouette_avg_ward <- mean(silhouette_ward[, 3])
# Guardar resultados en la tabla
silhouette_results <- rbind(silhouette_results,
data.frame(k = k,
Complete = silhouette_avg_complete,
Ward = silhouette_avg_ward))
}
# 5. Mostrar la tabla con los valores de Silhouette
print(silhouette_results)
k Complete Ward
1 2 0.4794811 0.2849436
2 3 0.3920006 0.2689969
3 4 0.3911023 0.1569887
4 5 0.2780641 0.1644334
5 6 0.1795929 0.1437603
6 7 0.1871729 0.1592385
7 8 0.1839689 0.1730134
8 9 0.1834415 0.1882923
9 10 0.1852607 0.1930730
Se utilizó la distancia euclidiana observando una estructura en dos clusters bien definidos en el dendrograma. Se evidencia que más de dos clusters degradan la calidad del agrupamiento.Esto es contrario a lo esperado, ya que por el conocimiento del negocio se esperaría que se generarán clusteres por zonas.
plot(hc_complete, cex = 0.6, main = "Dendograma Viviendas", las=1,
ylab = "Distancia euclidiana", xlab = "Grupos")
rect.hclust(hc_complete, k = 12, border = 2:5)
plot(hc_ward, cex = 0.6, main = "Dendograma Viviendas", las=1,
ylab = "Distancia euclidiana", xlab = "Grupos")
rect.hclust(hc_ward, k = 12, border = 2:5)
Como reultado se observa que existe heterogenidad y presencia de diferentes zonas. Pero esto no se está reflejando en los clusteres. Quizás La distancia Euclidiana favorece las variables con mayores rangos y puede no capturar bien las diferencias entre categorías.Se realizaron pruebas disminuyendo el número de variables, sin embargo los resultados del índice de Sillouethe no variaron demasiado respecto al resultado original.En ese sentido el método de Ward, muestra una mejor clasificación de grupos aunque en ambos casos el k con mejor resultado es 2.
Nuevamente se confirmar que el mejor número de clusters parece ser 2, ya que tiene el mayor índice de Silhouette (0.586).A medida que aumenta el número de clusters, el índice de Silhouette disminuye. Para k = 3 baja a 0.368, indicando que los clusters se están volviendo menos distinguibles. Para k ≥ 4, los valores siguen disminuyendo hasta 0.218, lo que sugiere que los clusters se superponen demasiado. No hay una mejora significativa al aumentar k por lo que se podría concluir que no hay una estructura natural clara en los datos más allá de 2 grupos principales.
El análisis de clustering es una técnica de aprendizaje no supervisado utilizada para agrupar observaciones similares en función de sus características. En este caso, se aplica el algoritmo k-means sobre el conjunto de datos vivienda_scale, previamente normalizado, para identificar patrones en las propiedades.
Se generan dos soluciones de agrupamiento: k = 2 (dos clusters) y k = 3 (tres clusters)
El parámetro nstart = 25 se usa para ejecutar el algoritmo 25 veces con diferentes inicializaciones y seleccionar la mejor solución basada en la minimización de la varianza intra-cluster. Para visualizar los resultados, se utilizan gráficos de dispersión que muestran la distribución de los clusters generados para k = 2 y k = 3.
set.seed(123) # Para reproducibilidad
kmeans_result2 <- kmeans(vivienda_scale, centers = 2, nstart = 25)
kmeans_result3 <- kmeans(vivienda_scale, centers = 3, nstart = 25)
kmeans_result4 <- kmeans(vivienda_scale, centers = 4, nstart = 25)
plot2<-fviz_cluster(kmeans_result2, data = vivienda_scale) + ggtitle("Clusters con k = 2")
plot3<-fviz_cluster(kmeans_result3, data = vivienda_scale)+ ggtitle("Clusters con k = 3")
plot4<-fviz_cluster(kmeans_result4, data = vivienda_scale) + ggtitle("Clusters con k = 4")
# Mostrar en una cuadrícula más equilibrada (2 filas, 2 columnas)
grid.arrange(plot2, plot3, plot4, ncol = 2, nrow = 2)
Los gráficos generados permiten evaluar la separación de los grupos en cada caso. Si los clusters están bien definidos y compactos con una clara separación entre ellos, el número de clusters elegido es adecuado. Si hay una superposición significativa, es posible que la estructura de los datos no sea óptima para k-means o que sea necesario ajustar k para mejorar la segmentación.
El análisis comparativo entre k = 2, k = 3 y k = 4 ayuda a determinar cuál es el número de clusters que mejor representa la estructura de los datos.
En este caso, luego de aplicar ambos métodos se ve que K-means muestra mejores resultados ya que optimiza directamente la inercia intra-cluster (minimiza la varianza dentro de cada grupo), lo que tiende a producir clusters más compactos y bien separados.El clustering jerárquico (método Ward o Complete) forma clusters basándose en una estrategia aglomerativa, es decir, agrupa los puntos secuencialmente sin optimización posterior. Esto puede generar grupos menos homogéneos si los datos no tienen una estructura jerárquica clara.
Siendo así, se identifica que los datos de vivienda pueden ser agrupados en 4 grandes grupos bien definidos según el método K-means. Lo que guarda más sentido respecto a las zonas y la naturaleza de los datos de vivienda.
El Análisis de Correspondencia es un método estadístico utilizado para representar posibles asociaciones entre variables categóricas, es decir la asociación entre sus categorías, con el fin establecer si existe, patrones o estructuras en los datos.Dado que el Análisis de Correspondencia se basa en tablas de frecuencia, primero se debe construir una tabla que relacione las variables categóricas:
tabla <- table(vivienda_clean$zona, vivienda_clean$estrato)
colnames(tabla) <- c("Estrato 3", "Estrato 4", "Estrato 5", "Estrato 6" )
tabla
Estrato 3 Estrato 4 Estrato 5 Estrato 6
Zona Centro 61 8 0 0
Zona Norte 318 231 505 85
Zona Oeste 36 64 192 513
Zona Oriente 199 7 2 0
Zona Sur 264 1206 1259 734
Debido a que el Análisis de Correspondencia se basa en la descomposición de la tabla de contingencia, que muestra la frecuencia conjunta de dos o más variables categóricas, se aplica el estadístico de Pearson (Chi-cuadrado) que mide qué tan independientes son las categorías de la tabla de contingencia.
pearson_test<- chisq.test(tabla)
pearson_test
Pearson's Chi-squared test
data: tabla
X-squared = 2584.6, df = 12, p-value < 2.2e-16
El resultado indica que se rechaza la hipótesis de independencia de las variables (p-value: 0.0000), indicando el tipo de relación entre ellas.
Finalmente se procede a realizar el análisis de correspondencia que consiste en estimar las coordenadas para cada uno de los niveles de ambas variables y representarlas en un plano cartesiano
resultados_ac <- CA(tabla)
El gráfico nos permite establecer relaciones y validarlas como por ejemplo que el estrato 6 se encuentra ubicado en la Zona Oeste, los estratos 4 y 5 están ubicados principalmente en la Zona Sur y Norte y que el estrato 3 está presente en las Zonas Oriente y Centro.
Para medir el grado de representatividad del proceso ahora se calculan los valores de la varianza acumulada, utilizando para ello los valores propios de la matriz de valores propios resultante del análisis de correspondencia.
valores_prop <-resultados_ac$eig ; valores_prop
eigenvalue percentage of variance cumulative percentage of variance
dim 1 0.31044273 68.270974 68.27097
dim 2 0.12927420 28.429320 96.70029
dim 3 0.01500447 3.299707 100.00000
A continuación se grafica el porcentaje de varianza explicado. Los resultados indican que la primera componente resumen el 68.3% y los dos primeros componentes prepresentados en el plano factorial, mientras que los dos primeros ejes resumen un 96.7% de los datos.
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")
Adicionalmente, se realizó un ACM para las tres variables categóricas del dataset de vivienda para analizar la relación entre ellas: tipo, zona y barrio:
# Seleccionar variables categóricas
vivienda_cat <- vivienda_clean[, c("tipo", "zona", "estrato")]
vivienda_cat$estrato <- as.factor(vivienda_cat$estrato)
# Aplicar Análisis de Correspondencias Múltiples
acm_result <- MCA(vivienda_cat, graph = TRUE)
Cómo lo indica el conocimiento del mercado inmoviliario la zona y el estrato ocurren frecuentemente juntas, como se ve en el anterior gráfico. Por ejemplo, que en la zona oeste se encuentra el estrato más alto, esto afirma lo que se evidenció en el Análisis de Correspondencia simple entre estrato y zona. Por otra parte, la variable tipo, al acercarce al eje 0,0 indica que tiene una baja contribución en la diferenciación de grupos, a diferencia del estrato y la zona que están lejos del origen, por lo que son más distintivos para definir un grupo particular.
A partir del Análisis de Componentes Principales (ACP), se identificó que el precio de las viviendas está altamente correlacionado con el área construida, el número de parqueaderos y el número de baños. Estos factores son los principales determinantes del valor de una propiedad por ser variables asociadas a la comodidad y que suelen estar relacionados con las viviendas en estratos altos.
La variable “piso” tiene una influencia menor en la variabilidad del precio, sugiriendo que la altura del apartamento no es un factor determinante, sino que puede estar relacionado con la ubicación y accesibilidad.
La correlación entre “habitaciones” y “piso” en los componentes secundarios sugiere que la distribución de estas características está más influenciada por la ubicación que por el tipo de vivienda en sí.
El análisis de conglomerados (método jerárquico) indica que los datos presentan una segmentación natural en dos grandes grupos, lo que podría reflejar la existencia de dos mercados diferenciados, posiblemente asociados a distintos niveles socioeconómicos o zonas geográficas.
La variable “zona” mostró un impacto significativo en la clasificación de los clústeres en el método jerarquico, donde se pudieron agrupar los datos en 4 grandes grupos bien diferenciados. Sugiriendo que la metodología empleada (k-means) es más efectiva para la segmentación del mercado de viviendas.
La validación del clustering mediante el índice de Silhouette confirmó que un número de dos conglomerados es el más adecuado para la estructura de los datos. Sin embargo, la variabilidad dentro de los grupos indica que podrían existir más subgrupos no detectados con este método.
Se recomienda enfocar la estrategia de valoración en el número de baños, el área construida y el número de parqueaderos, dado su fuerte impacto en el precio de las viviendas.
Implementar estrategias de marketing diferenciadas para los dos principales segmentos identificados en el análisis de conglomerados.
Explorar métodos adicionales de segmentación, como el análisis de redes o el uso de modelos de machine learning, para identificar subgrupos más específicos dentro del mercado.