Introducción

El objetivo de este trabajo es aplicar técnicas de análisis multivariado que permita acercarnos más a las características más relevantes del mercado inmobiliario de viviendas en Cali. Para ello, se utiliza una base de datos que contiene información de variables con las características y venta de viviendas en Cali.

El trabajo se divide en cuatro partes. En la primera parte se describe la metodología empleada para limpiar, imputar y explorar la base de datos, utilizando herramientas estadísticas y computacionales. En la segunda parte se presentan los resultados del análisis de componentes principales. En la tercera parte se presentan los análisis de conglomerados y en la cuarta el análisis de correspondencias.

Objetivos

Objetivo general:

Realizar un análisis del mercado de viviendas en Cali, aplicando métodos estadísticos para análisis multivariado, a saber: análisis de componentes principales, anpalisis de conglomerados y análisis de correspondencias.

Métodos

En esta sección se abordan las principales actividades desarrolladas para garantizar la calidad e integridad de la información suministrada. Se hace un preprocesamiento consistente en identificar e imputar valores faltantes, y posteriormente se aplican los metodos de análisis de componentes principales, de conglomerados y de correspondencias

Preparación de la base de datos

En este primer paso cargamos la base de datos que contiene 8322 registros y 13 variables.

data("vivienda")
vivienda

A continuación, se obtienen los indicadores básicos de las variables:

library(psych)
resu <- describe(vivienda)
format(round(resu, 2), nsmall = 2)

Se observan valores faltantes en todas las variables (aparecen 8327 cuando en la tabla inicial se informan 8330), además en piso y parquea los faltantes superan los 2300 registros.

El proceso de limpieza consistirá en la recodificación de las variables categóricas barrio y tipo. Posteriormente se imputarán los valores faltantes para que la base tenga la calidad requerida para la implementación de análisis de componentes principales, análisis de clúster y análisis de correspondencias.

Eliminación de valores faltantes de id.

Teniendo en cuenta que la variable id es la que se utiliza para identificar las viviendas, se requiere eliminar los valores faltantes (na) y no se observan duplicados por id

# Eliminación de los valores NA del id
vivienda <- vivienda[!is.na(vivienda$id), ]

duplicados <- duplicated(vivienda$id) # genera una vista con las columnas duplicadas
vivienda_con_duplicados <- vivienda[duplicados, ] # genera una tabla con los duplicados
head(vivienda_con_duplicados) # Revisar el subconjunto de datos
vivienda <- subset(vivienda, !duplicados)

Para los análisis de precios, no se recomienda usar la variable del precio de la vivienda porque varía en función del área, por lo tanto, se calcula una variable muy usada en el mercado inmobiliario: el precio por metro. Para este análisis se multiplica por mil para que los análisis sean más faciles de leer.

# crear la variable de precio por metro cuadrado
vivienda$p_m2 <- vivienda$preciom / vivienda$areaconst * 1000
vivienda$zona <- gsub("Zona ", "", vivienda$zona)

Imputación de valores faltantes

Identificamos las variables con valores faltantes

# Ver columnas con NA
na_values <- colSums(is.na(vivienda))  %>% data.frame()
na_values

La variable piso y parqueaderos presentan valores en blanco (na), trataremos las imputaciones por separado.

Imputación piso

Existen distintas técnicas para imputar valores faltantes, por ejemplo, la media, la moda, la mediana, sin embargo, como la variable de interes es una variable discreta y contamos con otras variables que ayudan a identificar el valor más probable de la variable, se utilizó la librería mice y el método MCC. Este método predice los valores faltantes utilizando la media condicional y luego ajusta los valores predichos para que coincidan con la distribución de los valores observados. Esta técnica se aplicó para sustituir los valores faltantes de la variable piso.

Para utilizar este método, se convierten las variables categóricas en continuas (zona, barrio y tipo) con la función factor, se ajusta con 50 iteraciones.

vivienda$piso <- as.numeric(vivienda$piso)

ggplot(vivienda, aes(x = .data[["piso"]])) +
  geom_bar() +
  labs(title = "Distribución de 'piso' antes de la imputación")

na_piso <- sum(is.na(vivienda$piso))
mensaje <- paste("Hay", na_piso, "valores en blanco")
print(mensaje)
## [1] "Hay 2635 valores en blanco"
######3.1 convertir variables categóricas a numéricas ######
# Convertir la variable "tipo" a numérica

vivienda$tipo_num <- as.numeric(factor(vivienda$tipo))
vivienda$barrio_num <- as.numeric(factor(vivienda$barrio))
vivienda$zona_num <- as.numeric(factor(vivienda$zona))

######3.2 Imputar la variable piso con el paquete mice ######

# Crear un conjunto de datos con las variables relevantes para la imputación
data_impute <- vivienda[, c("estrato", "preciom", "areaconst", "banios", "habitaciones", "tipo_num", "barrio_num", "zona_num", "piso")]

# Realizar la imputación utilizando el método MICE (Multiple Imputation by Chained Equations)
imputed_data <- mice(data_impute, method = "pmm", m = 5, maxit = 50, printFlag = FALSE)

# Combinar los conjuntos de datos imputados en un único conjunto de datos
imputed_data_complete <- complete(imputed_data)

# Agregar la columna imputada "piso_imp" a la tabla vivienda
# vivienda$piso_imp <- imputed_data_complete$piso
vivienda$piso <- imputed_data_complete$piso

A continuación se presenta el gráfico con la variable ajustada con la imputación, no se aprecian cambios abruptos en la distribución de frecuencias.

ggplot(vivienda, aes_string(x = "piso")) +
  geom_bar() +
  labs(title = "Distribución de 'piso' después de la imputación")

Imputación parqueaderos

En el caso de la variable de número de parqueaderos (parquea), al tabular la información por estratos, se observa que no hay valores de cero, es decir que en la base no tendrían viviendas sin parqueadero, para hacer la imputación se podría asumir que si el campo está en blanco es porque no hay parqueadero. Se observa que los NA se concentran especialmente en estrato 3 y 4, así las cosas, se sustituyen los NA por ceros.

ggplot(data = vivienda, aes_string(x = "parqueaderos")) +
  geom_bar(stat = "count", position = "identity") +
  labs(x = "Parqueaderos", y = "Frecuencia", title = "Distribución de parqueaderos") +
  theme_minimal()

tabla_na <- table(factor(vivienda$estrato, levels = unique(vivienda$estrato)), ifelse(is.na(vivienda$parqueaderos), "Con NA", "Sin NA")) %>% data.frame()

# Convertir la tabla a formato Markdown
tabla_markdown <- knitr::kable(tabla_na, format = "markdown")

# Mostrar la tabla en Markdown
tabla_markdown
Var1 Var2 Freq
3 Con NA 769
4 Con NA 488
5 Con NA 228
6 Con NA 117
3 Sin NA 684
4 Sin NA 1641
5 Sin NA 2522
6 Sin NA 1870
na_parquea <- sum(is.na(vivienda$parqueaderos))
mensaje <- paste("Hay", na_parquea, "valores en blanco")
mensaje
## [1] "Hay 1602 valores en blanco"

En este paso se reemplazan los NA por ceros.

######Imputar los valores NA de la variable parquea con ceros
vivienda$parqueaderos <- replace(vivienda$parqueaderos, is.na(vivienda$parqueaderos), 0)
na_parquea <- sum(is.na(vivienda$parqueaderos))
mensaje <- paste("Hay", na_parquea, "valores en blanco")
mensaje
## [1] "Hay 0 valores en blanco"
rm(barrio_frec, na_values, tabla_na, vivienda_con_duplicados, data_impute, imputed_data, imputed_data_complete) # borrado de tablas que no se usan

En resumen, en esta sección de preparación de las bases de datos, se eliminaron valores NA y se imputaron valores faltantes en parqueaderos y piso.

# Crear la nueva tabla vivienda_work
vivienda_work <- vivienda[, c("id", "piso", "estrato", "areaconst", "parqueaderos", "preciom", "banios", "habitaciones", "p_m2", "tipo_num", "zona_num")]

Matriz de correlación

La matriz de correlación es una herramienta vital en la etapa exploratoria del análisis de datos para identificar patrones y relaciones que pueden ser útiles para análisis posteriores y modelos predictivos.

Para facilitar el análisis, se excluirán variables que para esta entrega, no se analizarán: latitud, longitud o barrio.

# Crear la matriz de correlación
cor_matrix <- cor(vivienda_work)

# Graficar la matriz de correlación
corrplot(cor_matrix, method = "color", type = "upper", 
         tl.col = "black", tl.srt = 45, 
         title = "Matriz de Correlación de vivienda")

Relaciones Más Notables: - Piso: Tiene una correlación negativa moderada con zona_num. Esto sugiere que, en ciertas áreas, los pisos más altos pueden tener una tendencia inversa según la zona.

  • Estrato: Presenta una correlación positiva moderada con areaconst, preciom, y parqueaderos, lo que significa que a medida que aumenta el estrato, generalmente también aumentan el área construida, el precio y el número de parqueaderos. La correlación con habitaciones también es positiva, pero menos fuerte.

  • Area Construida (areaconst): Tiene una fuerte correlación positiva con preciom y parqueaderos, indicando que propiedades con mayor área construida tienden a tener un mayor precio y más parqueaderos. También muestra una correlación positiva con el número de baños y habitaciones.

  • Parqueaderos: Está fuertemente correlacionado de manera positiva con preciom, sugiriendo que propiedades con más parqueaderos tienden a ser más caras. Correlaciones positivas también se observan con areaconst y baños.

  • Precio (preciom): Tiene una correlación positiva fuerte con areaconst y parqueaderos, así como con estrato, lo cual es intuitivo: propiedades más caras tienden a tener mayor área construida, más parqueaderos y estar en estratos más altos. También muestra correlaciones positivas con baños y habitaciones.

  • Baños: Muestra correlaciones positivas con areaconst, parqueaderos, preciom y habitaciones, sugiriendo que propiedades con más baños tienden a ser más grandes, más caras, y tener más parqueaderos y habitaciones.

  • Habitaciones: Presenta correaciones positivas con areaconst, preciom y baños, lo que es lógico ya que más habitaciones suelen acompañar a un mayor número de baños y área construida. Interesantemente, muestra una correlación positiva fuerte con tipo_num, lo que puede indicar que ciertos tipos de propiedades tienen sistemáticamente más habitaciones.

  • Precio por Metro Cuadrado (p_m2): Muestra una correlación moderada con ciertas variables, pero es menos significativa que las otras correlaciones observadas.

  • Tipo (tipo_num): Correlaciona de manera interesante con habitaciones y zona_num, lo que podría significar diferencias en las características de los distintos tipos de propiedades según la zona.

  • Zona (zona_num): Tiene una correlación negativa moderada con piso, y muestra otras correlaciones ligeras que varían, lo cual sugiere diferencias en las características de propiedades según la zona.

Conclusión: Este gráfico facilita la identificación de relaciones lineales entre las variables en tu conjunto de datos. Destaca asociaciones significativas, como la relación entre estrato, areaconst, y preciom, ayudando a comprender cómo las distintas variables se influencian mutuamente.

Análisis de componentes principales PCA

El PCA se utiliza para reducir la dimensionalidad de un conjunto de datos, conservando la mayor cantidad posible de variabilidad.

data("vivienda_work")

viviendaZ= scale(vivienda_work[,2:5]) 
res.pca <- prcomp(viviendaZ)
fviz_eig(res.pca, addlabels = TRUE)

El primer componente principal explica el 46.4% de la varianza total de los datos. El segundo componente principal explica el 28.9% de la varianza total de los datos. En conjunto, estos dos componentes explican aproximadamente el 75.3% de la variancia total de los datos, lo que sugiere que estos dos componentes capturan bien la mayoría de la información contenida en las variables.

fviz_pca_var(res.pca,
col.var = "contrib", # Color by contributions to the PC
gradient.cols = c("#FF7F00",  "#034D94"),
repel = TRUE     # Avoid text overlapping
)

Esta gráfica de Análisis de Componentes Principales muestra la relación entre varias variables en un espacio de dos dimensiones principales (Dim1 y Dim2).

Relaciones Entre Variables:

  • Piso: La variable piso tiene una gran contribución a Dim2 (28.9%), como se ve por la flecha azul. Su dirección indica que está fuertemente alineada con Dim2 y relativamente poco asociada con Dim1.

  • Areaconst, Parqueaderos, y Estrato: Estas variables están muy alineadas con Dim1, indicando una fuerte correlación entre ellas y una fuerte influencia en Dim1.

Las direcciones similares de areaconst, parqueaderos, y estrato indican que estas variables están positivamente correlacionadas. Cuando una de estas aumenta, las otras dos también tienden a aumentar.

Correlaciones Entre Variables:

Estrato, Parqueaderos y Area Const: Las flechas de estas tres variables están muy cerca unas de otras y apuntan en una dirección similar, lo que sugiere que son variables positivamente correlacionadas. Entidades con mayor área construida tienden a estar en estratos más altos y a tener más parqueaderos. Piso: Está casi perpendicular a las variables areaconst, parqueaderos, y estrato, lo cual indica que no están fuertemente correlacionadas con piso.

Conclusión:

Este análisis de componentes principales proporciona una visión clara de cómo se relacionan las variables originales entre sí en términos de la varianza total en los datos. Las principales observaciones incluyen:

Piso tiene una fuerte contribución a la segunda dimensión (Dim2) pero no está estrechamente correlacionada con otras variables como areaconst, estrato, y parqueaderos.

Areaconst, parqueaderos y estrato están fuertemente correlacionadas y contribuyen significativamente a la primera dimensión (Dim1).

Análisis de conglomerados

El análisis de conglomerados es un método estadístico que agrupa objetos similares según sus características. Al aplicar este análisis, se identifican grupos homogéneos de objetos o individuos. Dentro de cada grupo, los objetos son más parecidos entre sí que con los de otros grupos. El proceso implica seleccionar variables para medir las características y luego aplicar un algoritmo de agrupamiento para formar conglomerados. Los algoritmos pueden ser jerárquicos o no jerárquicos, según cómo se construyan los grupos.

datos_escalados <- scale(vivienda_work)

determinacion del número de cluster:

# Método del codo
fviz_nbclust(datos_escalados, kmeans, method = "wss") +
  geom_vline(xintercept = 3, linetype = 2) +  # Modifica el número de intersección según el gráfico generado
  labs(subtitle = "Elbow method")

De acuerdo con la gráfica, el número de cluster óptimo es 3

Aplicar K_median

set.seed(123)  # Para garantizar resultados reproducibles
kmeans_result <- kmeans(datos_escalados, centers = 3, nstart = 25)

Visualizar los resultados

# Agregar el número de cluster a los datos originales
vivienda_work$cluster <- as.factor(kmeans_result$cluster)

# Visualización de los clusters
fviz_cluster(kmeans_result, data = datos_escalados, 
             geom = "point", stand = FALSE, 
             ellipse.type = "norm", ggtheme = theme_minimal())

# Graficar el dendograma


### Dendograma basado en los centroides

# Calcular las distancias entre los centroides
dist_centroids <- dist(kmeans_result$centers, method = "euclidean")

# Clustering jerárquico basado en los centroides
hclust_centroids <- hclust(dist_centroids, method = "complete")

# Graficar el dendograma
fviz_dend(hclust_centroids, rect = TRUE, show_labels = TRUE, palette = "jco")

Interpretación de los cluster

El dendograma muestra que las observaciones 1 y 2 son muy similares entre sí, como se ve en su unión a una baja altura. La observación 3 es significativamente diferente de las observaciones 1 y 2, lo que se representa en su unión a una altura más alta. Dos Clústeres Mayoritarios: Si se decide cortar el dendograma a una altura que minimiza la unión de clústeres disímiles (ej., cerca de 3), se obtendrán dos grupos o clústeres.

# Resumen de características de cada cluster
vivienda_work %>% 
  group_by(cluster) %>% 
  summarise_all(mean)

En la tabla anterior se diferencian los grupos así Hay una diferenciación en la cantidad de baños, el número de pisos y el área construida, pareciera que el cluster 1 está asociado al estrato 6, el cluster 2 al estrato 4 y el cluster 3 al estrato 5. El área construida es de 163 mts, 93 y 329 correspondientemente.

Análisis de correspondencias

El análisis de correspondencias es una técnica estadística utilizada para explorar la relación entre dos o más variables categóricas en un conjunto de datos y permite visualizar las relaciones entre las variables y los individuos en un espacio de baja dimensión.

# Crear la nueva tabla vivienda_work
vivienda_cat <- vivienda[, c("zona", "estrato", "tipo")]

Relación estrato - zona

En primer lugar, se hace una gráfica para ver el comportamiento de estas dos variables

# Crear un dataframe con el conteo por zona y estrato
conteo_zona_estrato <- vivienda %>%
  group_by(zona) %>%
  count(estrato)
# Crear el gráfico de barras
ggplot(conteo_zona_estrato, aes(x = fct_reorder(zona, n), y = n, fill = estrato)) +
  geom_bar(stat = "identity") +
  labs(title = "Distribución de viviendas por estrato",x = "Zona", y = "Unidades", fill = "Estrato") +
  theme_test()

Creación de tabla de contingencia

tabla <- table(vivienda_cat$zona, vivienda_cat$estrato)
colnames(tabla) <- c("Estrato 3", "Estrato 4", "Estrato 5", "Estrato 6" )
tabla
##          
##           Estrato 3 Estrato 4 Estrato 5 Estrato 6
##   Centro        105        14         4         1
##   Norte         572       407       769       172
##   Oeste          54        84       290       770
##   Oriente       340         8         2         1
##   Sur           382      1616      1685      1043

Prueba de chi-cuadrado

chisq.test(tabla)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla
## X-squared = 3830.4, df = 12, p-value < 2.2e-16

El resultado de la chi-cuadrado muestra que hay asociaciones fuertes entre las variables utilizadas. En este caso se rechaza la hipótesis nula, es decir que las variables son dependientes.

Gráfico de análisis de correspondencias

resultados_ac <- CA(tabla)

Extraer y mostrar valores propios (eigenvalores)

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

Visualizar la varianza explicada

fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")

Relación zona- tipo

# graficar las unidades por estrato y tipo
ggplot(vivienda, aes(fill = tipo, y = after_stat(count), x = estrato)) +
  geom_bar(position = "dodge") +
  labs(title = "Distribución de Tipos de Vivienda por estrato",
       x = "Estrato",
       y = "Número de viviendas") +
  theme_test()

Crear tabla de contingencia

tabla2 <- table(vivienda_cat$tipo, vivienda_cat$estrato)
colnames(tabla2) <- c("Estrato 3", "Estrato 4", "Estrato 5", "Estrato 6" )
tabla2
##              
##               Estrato 3 Estrato 4 Estrato 5 Estrato 6
##   Apartamento       639      1404      1766      1291
##   Casa              814       725       984       696

Prueba chi-cuadrado

chisq.test(tabla2)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla2
## X-squared = 224.33, df = 3, p-value < 2.2e-16

Al igual que la relación entre zona y estrato, la prueba chi-cuadrado entre la relación de las variables estrato y tipo de vivienda muestra que las variables son dependientes.

Gráfico de análisis de correspondencias

resultados_ac <- CA(tabla2)
valores_prop <-resultados_ac$eig ; valores_prop
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1  0.0269661                    100                               100

El indicador sugiere que solo hay una dimensión que explica el 100 de la varianza acumulada.

fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?

Correspondencias múltiples

Se utilizan las 3 variables categóricas zona, tipo y estrato

# Seleccionar las variables categóricas de interés
vivienda_cat <- vivienda[, c("zona", "estrato", "tipo")]
vivienda_cat$estrato <- as.factor(vivienda_cat$estrato)
# Realizar el Análisis de Correspondencias Múltiples (MCA)
mca_resultado <- MCA(vivienda_cat, graph = FALSE)

# Visualizar la varianza explicada por cada componente
fviz_screeplot(mca_resultado, addlabels = TRUE, ylim = c(0, 50)) +
  ggtitle("Porcentaje de Varianza Explicada por los Componentes") +
  ylab("Porcentaje de varianza explicado") +
  xlab("Componentes")

# Graficar el biplot de MCA
fviz_mca_biplot(mca_resultado, repel = TRUE) +
  ggtitle("Biplot de MCA") +
  theme_minimal()

# Visualizar las contribuciones de las variables a cada dimensión
fviz_mca_var(mca_resultado, choice = "mca.cor", repel = TRUE) +
  ggtitle("Contribuciones de las Variables a las Dimensiones") +
  theme_minimal()

El gráfico de porcentaje de varianza explicada muestra que el 80% de dicha varianza se concentra en los primeros 5 componentes.

El gráfico biplot de MCA visualiza cómo las categorías de cada variable se relacionan entre sí en el espacio de las dos primeras dimensiones principales. La proximidad entre puntos y vectores indica una alta similitud o relación. Centro y Oriente en la parte derecha del gráfico sugiere similaridades entre estas dos zonas Zona Sur y Estrato 4 y 5 están más cerca entre sí, sugiriendo que estas categorías tienen una asociación significativa. Estrato 3 y zona Centro están bastante cerca, sugiriendo que el estrato 3 es común en el centro.

Por último, en el gráfico de contribución de las variables a las dimensiones, muestran que zona y estrato: al estar situadas en el cuadrante superior derecho del gráfico, indica que son las variables que más influencia tienen sobre las dos primeras dimensiones (Dim1 y Dim2). Esto implica que estas dos variables son las que aportan más a explicar la varianza en los datos. Tipo: Esta variable se encuentra mucho más cerca del origen, indicando que su contribución a ambas dimensiones es bastante menor en comparación con “zona” y “estrato”.

Conclusiones

A continuación se presentarán las conclusiones a partir de los análisis elaborados:

  1. Con el análisis de componentes principales,

  2. A partir del análisis de conglomerados

  3. El análisis de correspondencias