1 Introducción

Este informe presenta un análisis del mercado inmobiliario mediante técnicas de análisis exploratorio, análisis de componentes principales (PCA) y clustering para identificar patrones en los datos, ademas de un analisis de correlacion para identificar las tendencias del tipo de vivienda por zona y estrato.

2 Carga de Librerías y Datos

En estas primeras estapas se cargaran los datos, aqui se verificara el tipo de datos para planear el procesamiento de estos.

# Instalar y cargar paquetes
#install.packages("devtools")
#devtools::install_github("dgonxalex80/paqueteMETODOS")

library(paqueteMETODOS)
library(dplyr)
library(ggplot2)
library(factoextra)
library(cluster)
library(NbClust)

# Cargar la base de datos
data("vivienda")

# primeros registros
head(vivienda)
## # A tibble: 6 × 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
## 6  1724 Zona N… 01          5     240        87            1      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

3 Preprocesamiento de Datos

En esta etapa se eliminan las filas con datos faltantes y columnas que se consideran no aportan valor al analisis como por ejemplo “id” en nuestra base de daos, ademas de eso se escala la tanla para evitar sesgo por la diferencia considerable entre los valores de las variables.

# Eliminar filas con valores faltantes
vivienda <- na.omit(vivienda)

# Eliminar ID si está presente
vivienda <- select(vivienda, -id)

# Normalizar datos numéricos
vivienda_scaled <- scale(select(vivienda, where(is.numeric)))

4 Matriz de Correlación

#install.packages("ggcorrplot")
library(ggcorrplot)
cor_matrix <- cor(vivienda_scaled)
ggcorrplot(cor_matrix, lab = TRUE, outline.color = "white")

Interpretación: La matriz de correlación muestra la relación entre variables numéricas. Se deberan eliminarán aquellas altamente correlacionadas para evitar redundancia en el análisis, sin embargo en esta matriz no se evidencia correlaciones mayores de 0.8 por lo que se procedera a evaluar todas las variables.

5 Análisis de Componentes Principales (PCA)

En este punto se consideraran los datos anteriormente procesados, donde ya se han convertido a tipo numerico y escalado, seguidamente se generan las graficas del peso de cada una de las dimensiones generadas.

# Se aplica el PCA  la matriz ya debidamente escalada.
pca_result <- prcomp(vivienda_scaled, scale. = TRUE)
summary(pca_result)
## Importance of components:
##                           PC1    PC2    PC3     PC4     PC5     PC6     PC7
## Standard deviation     1.9153 1.1866 0.9706 0.86731 0.67923 0.58305 0.49611
## Proportion of Variance 0.4585 0.1760 0.1178 0.09403 0.05767 0.04249 0.03077
## Cumulative Proportion  0.4585 0.6345 0.7523 0.84633 0.90399 0.94649 0.97725
##                            PC8
## Standard deviation     0.42658
## Proportion of Variance 0.02275
## Cumulative Proportion  1.00000
fviz_eig(pca_result)

# Visualizar las variables en el espacio de los componentes principales
fviz_pca_var(pca_result, col.var = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))

# Extraer las coordenadas de los individuos en las dos primeras componentes principales
individuos_pca <- as.data.frame(pca_result$x[, 1:2])

# Identificar los casos extremos en PC1 y PC2
casos_extremos_pc1 <- rbind(
  individuos_pca[which.min(individuos_pca$PC1), ],  # Caso con el valor más bajo en PC1
  individuos_pca[which.max(individuos_pca$PC1), ]   # Caso con el valor más alto en PC1
)

casos_extremos_pc2 <- rbind(
  individuos_pca[which.min(individuos_pca$PC2), ],  # Caso con el valor más bajo en PC2
  individuos_pca[which.max(individuos_pca$PC2), ]   # Caso con el valor más alto en PC2
)

# Asignar nombres y colores a los casos extremos
casos_extremos_pc1$color <- "blue"  # Color azul para los casos extremos en PC1
casos_extremos_pc2$color <- "red"   # Color rojo para los casos extremos en PC2

# Combinar los casos extremos en un solo data frame
casos_extremos <- rbind(casos_extremos_pc1, casos_extremos_pc2)

# Graficar los individuos en el espacio de las dos primeras componentes principales
fviz_pca_ind(pca_result, 
             col.ind = "#DEDEDE",  # Color gris para los individuos no destacados
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),  # Colores para el gradiente
             repel = TRUE) +  # Evitar superposición de etiquetas
  geom_point(data = casos_extremos, aes(x = PC1, y = PC2, color = color), size = 4) +  # Casos extremos
  scale_color_identity() +  # Usar los colores asignados directamente
  geom_text(data = casos_extremos, aes(x = PC1, y = PC2, label = rownames(casos_extremos)), 
            color = "black", vjust = -1) +  # Etiquetas de los casos extremos
  labs(title = "PCA: Individuos con Casos Extremos Destacados", 
       x = "Componente Principal 1 (PC1)", 
       y = "Componente Principal 2 (PC2)")

La tabla del peso que aporta cada variable a cada dimensón es considerado tambien y tiene gran importancia para el análisis del mercado.

# Cargar factoextra si no está cargado
library(factoextra)

head(pca_result$rotation)[, 1:5]
##                    PC1         PC2         PC3         PC4         PC5
## estrato      0.3077172  0.50056407 -0.24584930  0.19906424  0.59798057
## preciom      0.4618794  0.09751481 -0.18593609  0.17191067 -0.07143064
## areaconst    0.4322076 -0.25531365  0.01706766  0.03400749 -0.21476392
## parqueaderos 0.4205309  0.02720378 -0.10639674  0.25061507 -0.58673691
## banios       0.4527735 -0.15245991  0.09104367 -0.05357758  0.33211529
## habitaciones 0.2859637 -0.53145975  0.29517459 -0.36180188  0.29176111

Interpretación:

El gráfico de varianza explica cuántas dimensiones son necesarias para representar la mayor parte de la variabilidad en los datos.En la tabla se puede observar las variables que aportan mas peso o estan mas relacionadas a la dimension.

6 Determinación del Número Óptimo de Clusters

Para hallar el numero adecuado de cluster o aglomeración se usa el algoritmo que incluye todos los metodos de estimación de cluster adecuado.

#set.seed(123)
#nb_result <- NbClust(vivienda_scaled, distance = "euclidean", min.nc = 2, max.nc = 10, method = "kmeans", index = "all")

# Visualización
#fviz_nbclust(vivienda_scaled, FUNcluster = kmeans, method = "wss")

Resultados de Determinación del Número Óptimo de Clusters

Despues de implementar NbClust


Conclusión:

Se ha determinado el número óptimo de clusters mediante NbClust y el método del codo.

7 Segmentación de Viviendas con K-Means

Aplicado el anterior metodo, y se usa de forma directa la clasificación de los grupos, que este caso son 2.

set.seed(123)
kmeans_model <- kmeans(vivienda_scaled, centers = 2, nstart = 25)

# Agregar la asignación de cluster al dataset original
vivienda$cluster <- as.factor(kmeans_model$cluster)

# Visualización de los clusters
fviz_cluster(kmeans_model, data = vivienda_scaled) +
  labs(title = "Segmentación de Viviendas en 2 Clusters")

8 Análisis de Correspondencia

Se toman en cuenta variables categoricas como tipo de vivienda, zona y estrato para realizar el análisis

#install.packages("factoextra")
library(FactoMineR)

# Seleccionar solo variables categóricas (tipo, zona y estrato)
vars_categoricas <- vivienda[, c("tipo", "zona", "estrato")]

# Convertir estrato a factor si aún no lo es
vars_categoricas$estrato <- as.factor(vars_categoricas$estrato)

# Verificar y eliminar filas con NA para igualar las longitudes de datos
vars_categoricas <- vars_categoricas %>% na.omit()

# Aplicar MCA (Análisis de Correspondencias Múltiples)
mca_result <- MCA(vars_categoricas, graph = FALSE)

# Graficar los resultados
fviz_mca_var(mca_result, 
             repel = TRUE,  # Evita sobreposición de etiquetas
             col.var = "red",  # Color rojo para las etiquetas
             title = "Variable categories - MCA")

La varianza en CA se llama “inercia”, y mide la dispersión de los datos en el espacio multidimensional. Cuanta más inercia, más diversidad hay en las categorías, tambien nos puede ayudar a conocer la distribuciòn de peso en las dimensiones.

# Extraer los valores propios del MCA
eigenvalues <- mca_result$eig[, 1]  # Primera columna contiene los valores propios

# Calcular la varianza explicada por cada dimensión
var_explicada <- eigenvalues / sum(eigenvalues) * 100  # Expresada en porcentaje

# Calcular la varianza acumulada
var_acumulada <- cumsum(var_explicada)  # Suma acumulativa

# Crear un data frame para visualizar los resultados
df_varianza <- data.frame(
  Dimensión = 1:length(var_explicada),
  Varianza_Explicada = var_explicada,
  Varianza_Acumulada = var_acumulada
)

# Mostrar la tabla con los resultados
print(df_varianza)
##       Dimensión Varianza_Explicada Varianza_Acumulada
## dim 1         1          20.311831           20.31183
## dim 2         2          17.229221           37.54105
## dim 3         3          14.950400           52.49145
## dim 4         4          12.501430           64.99288
## dim 5         5          11.957504           76.95039
## dim 6         6          10.046741           86.99713
## dim 7         7           7.409599           94.40673
## dim 8         8           5.593274          100.00000
fviz_screeplot(mca_result, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")

Visualización de los Resultados

Análisis de componentes principales:

fviz_pca_var(pca_result, col.var = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))

Orientacion de la variable a cada dimension

Grafica de Cluster

# Gráfico de clusters
fviz_cluster(kmeans_model, data = vivienda_scaled, ellipse.type = "convex",
             palette = "jco", ggtheme = theme_minimal())

Distribución de promedios de los cluster, muestra el grafico de cajas y bigotes y permite visualizar las diferencias en los dos cluster de acuerdo a precio y tamaño del inmueble.

# Calcular el promedio de las variables de cada cluster:

vivienda %>%
  group_by(cluster) %>%
  summarise_all(mean)
## # A tibble: 2 × 13
##   cluster  zona  piso estrato preciom areaconst parqueaderos banios habitaciones
##   <fct>   <dbl> <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1 1          NA    NA    5.49    810.      308.         2.81   4.69         4.48
## 2 2          NA    NA    4.54    294.      113.         1.35   2.54         3.14
## # ℹ 4 more variables: tipo <dbl>, barrio <dbl>, longitud <dbl>, latitud <dbl>
# Se visualiza la distribución de la variables por cada cluster.

library(ggplot2)

ggplot(vivienda, aes(x = cluster, y = preciom, fill = cluster)) +
  geom_boxplot() +
  theme_minimal() +
  labs(title = "Distribución de Precios por Cluster",
       x = "Cluster", y = "Precio")

Conclusion

Basado en los resultados se pueden caracterizar dos cluster:

Cluster 1: Viviendas grandes con precios elevados.

Cluster 2: Viviendas pequeñas con precios accesibles.

Distribución de los cluster con respecto al area construida y el precio de la vivienda.

# Gráfico de dispersión con colores por cluster
ggplot(vivienda, aes(x = areaconst, y = preciom, color = cluster)) +
  geom_point() +
  labs(title = "Relación entre Área Construida y Precio por Cluster", x = "Área Construida", y = "Precio")

9 Conclusiones

10 Análisis de Componentes Principales (PCA)

El PCA reveló que los primeros dos componentes principales explican la mayor parte de la variabilidad en los datos.

Variable PC1 PC2
estrato 0.3077172 0.50056407
preciom 0.4618794 0.09751481
areaconst 0.4322076 -0.25531365
parqueaderos 0.4205309 0.02720378
banios 0.4527735 -0.15245991
habitaciones 0.2859637 -0.53145975

Primer Componente (PC1): Está fuertemente influenciado por el área construida, precio y número de baños, lo que indica que las viviendas más grandes y costosas tienden a agruparse en una misma dirección.

Segundo Componente (PC2): Diferencia propiedades por estrato y numero de habitaciones.

Conclusión:

El PCA sugiere que el precio está altamente correlacionado con el tamaño del inmueble y su número de baños.

11 Análisis de Conglomerados (Clustering)

La segmentación con K-means (k=2) identificó 2 grupos principales:

Cluster 1: Viviendas de alto costo: Mayor área construida y estrato.

Cluster 2: Viviendas más accesibles: Estratos bajos, menor área y precio.

Conclusión:

El clustering ayuda a identificar segmentos del mercado inmobiliario con necesidades diferentes, lo que puede ser útil para estrategias de precios y ubicación.

12 Análisis de Correspondencia

El análisis de correspondencia mostró que:

Los apartamentos predominan en ciertas zonas específicas.

Los barrios de estratos más altos tienen una distribución de tipos de vivienda diferente a los de estratos bajos.

13 Conclusión:

Las relaciones entre tipo, zona y barrio sugieren que ciertos barrios están especializados en tipos de vivienda específicos, lo cual puede ayudar en estudios de mercado.