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.
Reducir la dimensionalidad del conjunto de datos y visualizar la estructura de las variables en componentes principales para identificar características clave que influyen en la variación de precios y oferta del mercado.
Base de datos y variables:
#devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
library(paqueteMODELOS)
library(tidyverse)
library(ggplot2)
library(factoextra)
library(cluster)
library(NbClust)
library(mice)
data("vivienda")
dplyr::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…
# Visualizar las primeras filas
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>
La imputación es esencial para asegurar que el análisis posterior como el PCA no se vea afectado por la presencia de valores faltantes. No se deben incluir variables categóricas como estrato directamente en el análisis de punto 1 de PCA, ya que este requiere variables numéricas contínuas. Además, algunas variables, como zona y barrio, podrían ser importantes para segmentaciones o modelos posteriores, pero no se deben incluir en PCA directamente a menos que sean transformadas de forma adecuada.
En este caso, debido al contexto, se podría hacer uso del PCA para explorar cómo varían las propiedades en función de su precio, tamaño, y ubicación (si latitud y longitud son variables relevantes).
# Se calcula el porcentaje de valores NA para cada variable
porcentaje_na <- map_dfr(names(vivienda), ~ {
data.frame(variable = .x, porcentaje_na = round((sum(is.na(vivienda[[.x]])) / length(vivienda[[.x]])) * 100, 2))
})
# Ordenar variables por porcentaje de NAs de mayor a menor
porcentaje_na <- porcentaje_na %>%
arrange(desc(porcentaje_na))
# Diagrama
ggplot(porcentaje_na, aes(x = reorder(variable, porcentaje_na), y = porcentaje_na, fill = variable)) +
geom_bar(stat = "identity") +
labs(title = "Porcentaje de NA's en la base de datos vivienda",
x = "Variable",
y = "% NA's",
fill = "Variable") +
theme(legend.position = "bottom")
# Reviso la cantidad de valores NA por columna
colSums(is.na(vivienda))
## id zona piso estrato preciom areaconst
## 3 3 2638 3 2 3
## parqueaderos banios habitaciones tipo barrio longitud
## 1605 3 3 3 3 3
## latitud
## 3
La tabla indica que se presentan datos faltantes en vivienda, especialmente, en la variable piso, en la que, como se visualizó inicialmente, existen valores como “01”, “02”, “03”, etc; lo que indica que piso es una variable ordinal o categórica. Aunque los valores son numéricos, el hecho de que los valores representen categorías (primer piso, segundo piso, etc.) sugiere que no deben ser tratados para este caso (PCA).
Adicionalmente, de los datos, extraigo estrato por ser categórica ordinal y analizo la cantidad de columnas en el conjunto de datos y su respectivo tipo.
# Excluir la columna 'estrato' para la imputación y PCA
vivienda_sin_estrato <- vivienda[, !(names(vivienda) %in% c("estrato"))]
# Ver cuántas columnas hay en el conjunto de datos
num_columns <- ncol(vivienda_sin_estrato)
print(paste("Número de columnas a imputar:", num_columns))
## [1] "Número de columnas a imputar: 12"
# Verificar el tipo de cada columna para aplicar el método adecuado
column_types <- sapply(vivienda_sin_estrato, class)
print("Tipos de las columnas a imputar:")
## [1] "Tipos de las columnas a imputar:"
print(column_types)
## id zona piso preciom areaconst parqueaderos
## "numeric" "character" "character" "numeric" "numeric" "numeric"
## banios habitaciones tipo barrio longitud latitud
## "numeric" "numeric" "character" "character" "numeric" "numeric"
Se excluye la columna estrato antes de realizar la imputación y se utiliza mice con los métodos más apropiados según el tipo de variable: - pmm para las numéricas continuas (como preciom, areaconst, longitud, latitud). - mode para las variables categóricas (como piso, tipo, barrio). - mean o mode para las numéricas discretas (como banios, habitaciones, parqueaderos).
Aunque estrato no se incluye en PCA, es útil mantenerlo en el conjunto de datos para posteriores análisis. Por ello, se reincorpora a vivienda_completed después de la imputación, pero sin imputar, usando los valores originales.
# Asignar métodos de imputación para cada tipo de variable
methods <- rep("pmm", num_columns) # Asignamos 'pmm' para todas las columnas por defecto
methods[column_types == "character"] <- "mode" # Asignamos 'mode' a las columnas categóricas
# Ver los métodos asignados
print("Métodos de imputación:")
## [1] "Métodos de imputación:"
methods
## [1] "pmm" "mode" "mode" "pmm" "pmm" "pmm" "pmm" "pmm" "mode" "mode"
## [11] "pmm" "pmm"
# Realizar la imputación con los métodos definidos
vivienda_imputed <- mice(vivienda_sin_estrato,
method = methods,
m = 5) # Número de imputaciones
##
## iter imp variable
## 1 1 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 1 2 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 1 3 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 1 4 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 1 5 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 2 1 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 2 2 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 2 3 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 2 4 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 2 5 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 3 1 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 3 2 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 3 3 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 3 4 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 3 5 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 4 1 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 4 2 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 4 3 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 4 4 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 4 5 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 5 1 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 5 2 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 5 3 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 5 4 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## 5 5 id preciom* areaconst* parqueaderos* banios* habitaciones* longitud latitud*
## Warning: Number of logged events: 154
# Completar los datos imputados
vivienda_completed <- complete(vivienda_imputed)
# Volver a añadir la columna 'estrato' al conjunto imputado (sin imputar)
vivienda_completed$estrato <- vivienda$estrato
# Seleccionar solo las variables numéricas para PCA (sin 'estrato' ni variables
# categóricas)
vivienda_pca <- vivienda_completed[, c("preciom", "areaconst", "banios",
"habitaciones", "longitud", "latitud")]
PCA requiere que los datos estén estandarizados, por lo que se usa me aseguro en este paso de que que todas las variables numéricas tengan una media de 0 y una desviación estándar de 1, lo cual es importante para evitar que las variables con mayores rangos numéricos dominen el análisis.
# Estandarizar los datos (importante para PCA)
vivienda_pca_scaled <- scale(vivienda_pca)
Se aplica el PCA para extraer los componentes principales, los cuales representan combinaciones lineales de las variables originales. A continuación, se muestra un resumen del PCA, se extrae y visualiza la varianza explicada por cada componente, y se seleccionan las primeras dos componentes principales para analizar la distribución de las observaciones en el espacio reducido. Se incluyen gráficos como el biplot para visualizar tanto las observaciones como las variables, permitiendo una interpretación más clara de cómo las variables contribuyen a los componentes y cómo se distribuyen las observaciones en este nuevo espacio. También se realiza un gráfico Scree para evaluar la varianza explicada por cada componente y asegurar que el modelo elegido sea el adecuado. Este análisis facilita la comprensión de la estructura subyacente de los datos y permite visualizar patrones complejos de manera más sencilla.
# Realizar PCA
pca_result <- prcomp(vivienda_pca_scaled, center = TRUE, scale. = TRUE)
# Resumen de los resultados de PCA
summary_pca <- summary(pca_result)
print(summary_pca)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 1.6791 1.1117 0.8994 0.7809 0.57594 0.44074
## Proportion of Variance 0.4699 0.2060 0.1348 0.1016 0.05528 0.03238
## Cumulative Proportion 0.4699 0.6759 0.8107 0.9123 0.96762 1.00000
# Extraer la varianza explicada por cada componente principal
var_explained <- summary_pca$importance[2, ]
var_explained_table <- data.frame(Componente = paste("PC", 1:length(var_explained), sep=""),
Varianza_Explicada = var_explained)
print(var_explained_table)
## Componente Varianza_Explicada
## PC1 PC1 0.46990
## PC2 PC2 0.20599
## PC3 PC3 0.13482
## PC4 PC4 0.10163
## PC5 PC5 0.05528
## PC6 PC6 0.03238
# Extraer las coordenadas de las primeras 2 componentes principales
pca_data <- data.frame(pca_result$x)
first_two_components <- pca_data[, c("PC1", "PC2")]
first_two_components_table <- data.frame(Observación = 1:nrow(first_two_components),
PC1 = first_two_components$PC1,
PC2 = first_two_components$PC2)
# 1. Interpretación de las Cargas de los Componentes Principales
# Ver las cargas de los componentes principales
cargas <- pca_result$rotation
print(cargas)
## PC1 PC2 PC3 PC4 PC5
## preciom 0.4941020 0.12089745 0.30209718 0.46308184 0.17932937
## areaconst 0.5105018 -0.14698748 0.04610364 0.27178904 -0.69865863
## banios 0.5288669 -0.07353394 -0.08060616 -0.04725046 0.66584434
## habitaciones 0.3879867 -0.40742922 -0.39416295 -0.58090861 -0.11855830
## longitud -0.2304690 -0.61757652 -0.44790995 0.58694644 0.13584417
## latitud -0.1090928 -0.64107092 0.73764940 -0.16580826 0.06211844
## PC6
## preciom 0.63512240
## areaconst -0.39199986
## banios -0.51265375
## habitaciones 0.42022904
## longitud 0.04359139
## latitud -0.04060924
# 2. Visualización adicional: PCA Biplot
# Graficar el biplot para ver las variables y las observaciones
fviz_pca_biplot(pca_result,
repel = TRUE, # Evitar que las etiquetas se sobrepongan
habillage = vivienda_completed$zona, # Color por zona si es aplicable
col.var = "#034A94", # Color para las variables
col.ind = c("#DEDEDE", "#034A94")) + # Color para las observaciones
theme_minimal() +
labs(title = "PCA Biplot - Variables y Observaciones")
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
# ** Tabla de las cargas de las variables en los componentes principales **
cargas <- pca_result$rotation
cargas_table <- data.frame(Variable = rownames(cargas),
PC1 = cargas[,1],
PC2 = cargas[,2],
PC3 = cargas[,3],
PC4 = cargas[,4]) # Asumiendo 4 componentes principales
print(cargas_table)
## Variable PC1 PC2 PC3 PC4
## preciom preciom 0.4941020 0.12089745 0.30209718 0.46308184
## areaconst areaconst 0.5105018 -0.14698748 0.04610364 0.27178904
## banios banios 0.5288669 -0.07353394 -0.08060616 -0.04725046
## habitaciones habitaciones 0.3879867 -0.40742922 -0.39416295 -0.58090861
## longitud longitud -0.2304690 -0.61757652 -0.44790995 0.58694644
## latitud latitud -0.1090928 -0.64107092 0.73764940 -0.16580826
# Graficar las primeras dos componentes principales
ggplot(pca_data, aes(x = PC1, y = PC2)) +
geom_point(aes(color = vivienda_completed$zona)) +
labs(title = "Distribución de Observaciones según las Primeras 2 Componentes Principales",
x = "Componente Principal 1", y = "Componente Principal 2") +
theme_minimal()
# ** Tabla de las primeras dos componentes principales de las observaciones **
pca_first_two_table <- data.frame(Observación = 1:nrow(pca_data),
PC1 = pca_data$PC1,
PC2 = pca_data$PC2)
head(pca_first_two_table)
## Observación PC1 PC2
## 1 1 -0.3212733 -1.46688730
## 2 2 -1.1958851 -0.57708499
## 3 3 -0.4930901 -0.87116624
## 4 4 0.9695437 0.09458312
## 5 5 -1.4427968 -0.90742435
## 6 6 -0.8386151 0.50237322
# Graficar el Scree plot para visualizar la varianza explicada por cada componente
fviz_eig(pca_result, addlabels = TRUE, ylim = c(0, 100))
# ** Tabla de la varianza explicada por cada componente **
varianza_exp <- pca_result$sdev^2 / sum(pca_result$sdev^2) * 100
varianza_df <- data.frame(Componente = paste("PC", 1:length(varianza_exp)),
Varianza_Explicada = varianza_exp,
Varianza_Cumulativa = cumsum(varianza_exp))
print(varianza_df)
## Componente Varianza_Explicada Varianza_Cumulativa
## 1 PC 1 46.989909 46.98991
## 2 PC 2 20.599114 67.58902
## 3 PC 3 13.481574 81.07060
## 4 PC 4 10.163376 91.23397
## 5 PC 5 5.528433 96.76241
## 6 PC 6 3.237594 100.00000
# Visualización de las contribuciones de las variables a los componentes principales
fviz_pca_var(pca_result,
col.var = "contrib", # Color según las contribuciones de las variables
gradient.cols = c("#FF7F00", "#034D94"),
repel = TRUE) # Evitar la superposición del texto
# ** Tabla de las contribuciones de las variables **
contribuciones <- pca_result$rotation^2 # Cuadrado de las cargas para ver las contribuciones
contribuciones_df <- data.frame(Variable = rownames(contribuciones),
PC1_Contrib = contribuciones[,1],
PC2_Contrib = contribuciones[,2],
PC3_Contrib = contribuciones[,3],
PC4_Contrib = contribuciones[,4]) # Para cada componente
print(contribuciones_df)
## Variable PC1_Contrib PC2_Contrib PC3_Contrib PC4_Contrib
## preciom preciom 0.24413681 0.01461619 0.091262708 0.214444794
## areaconst areaconst 0.26061208 0.02160532 0.002125546 0.073869283
## banios banios 0.27970024 0.00540724 0.006497353 0.002232606
## habitaciones habitaciones 0.15053366 0.16599857 0.155364431 0.337454817
## longitud longitud 0.05311595 0.38140075 0.200623324 0.344506121
## latitud latitud 0.01190125 0.41097192 0.544126638 0.027492380
Con base en el gráfico y la tabla de contribuciones de las variables a los componentes principales (PC1, PC2, PC3, y PC4), se pueden hacer varias interpretaciones útiles para una inmobiliaria. En primer lugar, las variables “banios” y “latitud” muestran contribuciones significativas en las primeras componentes (PC1 y PC2, respectivamente), lo que sugiere que estas características tienen un impacto considerable en las propiedades inmobiliarias y podrían ser factores determinantes en la evaluación de las viviendas. Por ejemplo, un número mayor de baños podría correlacionarse con un mayor valor o calidad de la propiedad, y la latitud podría reflejar la ubicación geográfica, influyendo en aspectos como la accesibilidad o la ubicación deseable.
En segundo lugar, “habitaciones” muestra una contribución más equilibrada entre las primeras componentes, lo que indica que su influencia está distribuida en varias dimensiones de las viviendas y su valor. La variable “preciom” también presenta una contribución moderada, lo que implica que el precio de la vivienda podría estar relacionado de manera compleja con varias de las características del inmueble.
Para la inmobiliaria, esto significa que las características relacionadas con los baños, la ubicación geográfica (latitud) y el número de habitaciones son cruciales en la clasificación de las viviendas, mientras que el precio y el área también tienen su peso, pero quizás de manera más distribuida a lo largo de varias dimensiones. Esta información puede ayudar a identificar qué factores deben ser resaltados en las promociones o qué aspectos podrían ser mejorados en propiedades para aumentar su atractivo en el mercado.
# Obtener las observaciones con los valores extremos para PC1 y PC2
max_pc1_index <- which.max(pca_result$x[, "PC1"])
min_pc1_index <- which.min(pca_result$x[, "PC1"])
max_pc2_index <- which.max(pca_result$x[, "PC2"])
min_pc2_index <- which.min(pca_result$x[, "PC2"])
# Seleccionar los casos extremos
casos_vivienda <- rbind(pca_result$x[max_pc1_index, 1:2], pca_result$x[min_pc1_index, 1:2],
pca_result$x[max_pc2_index, 1:2], pca_result$x[min_pc2_index, 1:2])
rownames(casos_vivienda) <- c("Max_PC1", "Min_PC1", "Max_PC2", "Min_PC2")
casos_vivienda <- as.data.frame(casos_vivienda)
# Graficar las observaciones y casos extremos resaltados
fviz_pca_ind(pca_result,
col.ind = "#DEDEDE",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07")) +
geom_point(data = casos_vivienda, aes(x = PC1, y = PC2), color = "red", size = 3) +
labs(title = "Distribución de las Observaciones con Casos Resaltados",
x = "Componente Principal 1", y = "Componente Principal 2")
# ** Tabla de los casos resaltados **
casos_resaltados_table <- data.frame(Caso = c("Max_PC1", "Min_PC1", "Max_PC2", "Min_PC2"),
PC1 = c(casos_vivienda$PC1[1], casos_vivienda$PC1[2], casos_vivienda$PC1[3], casos_vivienda$PC1[4]),
PC2 = c(casos_vivienda$PC2[1], casos_vivienda$PC2[2], casos_vivienda$PC2[3], casos_vivienda$PC2[4]))
print(casos_resaltados_table)
## Caso PC1 PC2
## 1 Max_PC1 8.832208 -0.5129006
## 2 Min_PC1 -3.546521 -0.7474776
## 3 Max_PC2 -1.348126 2.5539203
## 4 Min_PC2 5.930591 -4.9252801
El gráfico y la tabla anterior de los casos extremos, permiten identificar las viviendas que se encuentran más alejadas de la “media” o distribución normal de tus datos en función de las componentes principales, lo que podría ser útil para detectar casos excepcionales o patrones inusuales en el mercado inmobiliario. Donde:
Max_PC1 y Min_PC1: Estas observaciones reflejan las viviendas que están en los extremos de la primera componente principal (PC1), que podría estar relacionada con características como el precio, tamaño, o alguna otra variable clave. Un valor alto de PC1 podría corresponder a una vivienda más cara o más grande, mientras que un valor bajo podría corresponder a viviendas más pequeñas o con características más económicas.
Max_PC2 y Min_PC2: Las observaciones de Max_PC2 y Min_PC2 están en los extremos de la segunda componente principal, que podría estar relacionada con otros aspectos de las viviendas, como la ubicación (zona), el tipo de construcción o alguna otra variable importante que no está completamente representada por PC1.
# Extraer la varianza explicada por cada componente
varianza_exp = pca_result$sdev^2 / sum(pca_result$sdev^2) * 100
# Crear un dataframe para visualizar la varianza explicada
varianza_df <- data.frame(
Componente = paste("PC", 1:length(varianza_exp)),
Varianza_Explicada = varianza_exp,
Varianza_Cumulativa = cumsum(varianza_exp)
)
# Mostrar la tabla con la varianza explicada y la varianza acumulada
print(varianza_df)
## Componente Varianza_Explicada Varianza_Cumulativa
## 1 PC 1 46.989909 46.98991
## 2 PC 2 20.599114 67.58902
## 3 PC 3 13.481574 81.07060
## 4 PC 4 10.163376 91.23397
## 5 PC 5 5.528433 96.76241
## 6 PC 6 3.237594 100.00000
Debido al análisis de varianza explicada, se tienen como opciones el retener los primeros tres componentes (PC1, PC2 y PC3) que explican el 81.1% de la varianza total, lo que da equilibrio entre simplificación y una representación más precisa de los datos. La considero ideal debido a que me interesa presentar a la empresa inmobiliaria una representación fiel y reducir la dimensionalidad; también está la opción de retener los primeros cuatro componentes (PC1, PC2, PC3 y PC4), pero, aunque explique el 91.2% de la varianza total la dimensionalidad sería más alta, lo que podría complicar la interpretación y el procesamiento.
Agrupar las propiedades residenciales en segmentos homogéneos con características similares para entender las dinámicas de las ofertas específicas en diferentes partes de la ciudad y en diferentes estratos socioeconómicos.
Primero, se realiza la normalización de las variables para asegurarnos de que todas las variables estén en la misma escala, como en el ejemplo visto en clase. Utilizando scale para aplicar la fórmula de z donde al valor de la variable se le resta la media y esto se divide en la desviación estándar.
# Estandarización de variables
vivienda_std <- scale(vivienda_completed[, c("preciom", "areaconst", "banios", "habitaciones", "longitud", "latitud")])
vivienda_std <- as.data.frame(vivienda_std)
El siguiente paso es calcular la matriz de distancias entre las viviendas. Se puede usar la distancia Euclidiana, Manhattan o Minkowski:
# Distancias Euclidianas
dist_matrix <- dist(vivienda_std, method = "euclidean")
# Distancias Manhattan
dist_matrix_manhattan <- dist(vivienda_std, method = "manhattan")
Se aplica el clustering jerárquico para identificar grupos de propiedades con características similares, lo que permite realizar segmentaciones efectivas y dirigir estrategias de marketing específicas para cada tipo de vivienda, se aplica utilizando la matriz de distancias y generamos un dendrograma para visualizar la agrupación de las viviendas:
# Aplicar clustering jerárquico
hc_vivienda <- hclust(dist_matrix, method = "complete")
# Graficar el dendrograma
plot(hc_vivienda, cex = 0.6, main = "Dendrograma de Viviendas", las = 1, ylab = "Distancia Euclidiana", xlab = "Viviendas",
col = "blue")
# Extraer los datos de fusión (unión de observaciones) del dendrograma
fusion_info <- hc_vivienda$merge
# Extraer las distancias en las que las observaciones se fusionan
distancias_fusion <- hc_vivienda$height
# Crear un dataframe con la información de las fusiones y las distancias
tabla_dendrograma <- data.frame(
Fusion_1 = fusion_info[, 1],
Fusion_2 = fusion_info[, 2],
Distancia = distancias_fusion
)
El número óptimo de clústeres se puede determinar visualmente a partir del dendrograma, utilizando el criterio del mayor salto de nodo a nodo y se agrega un bucle para probar valores de k entre 2 y 10. Calculamos el índice de Silhouette para cada valor y mostramos los resultados en una tabla. Seleccionamos el k con el índice de Silhouette más alto. También podemos usar un corte en el dendrograma para decidir cuántos clústeres crear.
Se calcula y se muestra además el índice de Silhouette promedio para el mejor número de clústeres.
# Probar diferentes valores de k y calcular el índice de Silhouette
silhouettes <- numeric(9) # Creamos un vector con 9 elementos para almacenar los resultados
for (k in 2:10) {
clusters <- cutree(hc_vivienda, k = k) # Aplico el corte al dendrograma
sil <- silhouette(clusters, dist_matrix)
silhouettes[k - 1] <- mean(sil[, 3]) # Silhouette[k - 1] porque el índice empieza en 2
}
# Mostrar el índice de Silhouette para cada k
silhouette_results <- data.frame(K = 2:10, Silhouette = silhouettes)
print(silhouette_results)
## K Silhouette
## 1 2 0.6350828
## 2 3 0.3396905
## 3 4 0.3089542
## 4 5 0.2784871
## 5 6 0.2783564
## 6 7 0.2760488
## 7 8 0.2743242
## 8 9 0.1787923
## 9 10 0.1789405
# Seleccionamos el mejor k según el índice de Silhouette
best_k <- 3 #silhouette_results$K[which.max(silhouette_results$Silhouette)]
cat("El mejor número de clústeres (k) según el índice de Silhouette es:", best_k, "\n")
## El mejor número de clústeres (k) según el índice de Silhouette es: 3
clusters <- cutree(hc_vivienda, k = best_k) # Aplicar el corte al dendrograma
sil <- silhouette(clusters, dist_matrix)
sil_avg <- mean(sil[, 3])
# Asignación los clústeres a los datos
vivienda_completed$Cluster <- as.factor(clusters)
Una vez que se han asignado los clústeres, podemos visualizarlos en un gráfico para ver cómo se agrupan las viviendas según las características estandarizadas.
# Crear la tabla con los resultados
resultados_clust <- vivienda_completed[, c("preciom", "areaconst", "Cluster")]
# Visualización de los clústeres en un gráfico
ggplot(vivienda_completed, aes(x = preciom, y = areaconst, color = as.factor(Cluster))) +
geom_point(size = 4, alpha = 0.7) +
geom_text(aes(label = Cluster), vjust = -0.8, check_overlap = TRUE) +
scale_color_brewer(palette = "Set1") +
theme_classic() +
labs(title = "Clústeres de Viviendas", color = "Clúster")
El índice de Silhouette es una medida de la calidad del agrupamiento. Un valor cercano a 1 indica un buen agrupamiento, mientras que valores cercanos a -1 indican que los grupos podrían no estar bien definidos. Podemos calcular este índice para evaluar cuán bien están agrupadas las viviendas.
# Cálculo del índice de Silhouette
sil <- silhouette(clusters, dist_matrix)
sil_avg <- mean(sil[, 3])
# Coeficiente de Silhouette promedio
cat("Coeficiente de Silhouette promedio k=", k, ": ", sil_avg)
## Coeficiente de Silhouette promedio k= 10 : 0.3396905
# K-means con el mejor número de clústeres
set.seed(123) # Para reproducibilidad
kmeans_result <- kmeans(vivienda_std, centers = best_k, nstart = 25)
# Asignar los clústeres de k-means a los datos
vivienda_completed$KMeans_Cluster <- as.factor(kmeans_result$cluster)
# Visualización de los clústeres de k-means
ggplot(vivienda_completed, aes(x = preciom, y = areaconst, color = KMeans_Cluster)) +
geom_point(size = 4, alpha = 0.7) +
scale_color_brewer(palette = "Set1") +
theme_classic() +
labs(title = "Clústeres de Viviendas (k-means)", color = "Clúster")
# Imprimir los clústeres asignados a cada observación
cat("Clúster asignado a cada observación:\n")
## Clúster asignado a cada observación:
# Imprimir los centros de los clústeres
cat("\nCentros de los clústeres:\n")
##
## Centros de los clústeres:
print(kmeans_result$centers)
## preciom areaconst banios habitaciones longitud latitud
## 1 -0.5466889 -0.4104291 -0.5476812 -0.2069967 1.2214706 1.15627996
## 2 -0.3766727 -0.4392935 -0.4002429 -0.3936802 -0.2886373 -0.44297473
## 3 1.1324151 1.1405333 1.1769326 0.8945689 -0.4331990 -0.09515185
# Imprimir el tamaño de cada clúster (número de elementos por clúster)
cat("\nTamaño de cada clúster:\n")
##
## Tamaño de cada clúster:
print(kmeans_result$size)
## [1] 1809 4232 2281
# Imprimir la suma total de las distancias dentro de los clústeres
cat("\nSuma total de las distancias dentro de los clústeres (tot.withinss):\n")
##
## Suma total de las distancias dentro de los clústeres (tot.withinss):
print(kmeans_result$tot.withinss)
## [1] 28083.01
# Imprimir la variabilidad entre los clústeres
cat("\nVariabilidad entre los clústeres (betweenss):\n")
##
## Variabilidad entre los clústeres (betweenss):
print(kmeans_result$betweenss)
## [1] 21842.99
# Imprimir el valor total del índice de Silhouette
sil_kmeans <- silhouette(kmeans_result$cluster, dist_matrix)
sil_kmeans_avg <- mean(sil_kmeans[, 3])
cat("\nÍndice de Silhouette promedio para k-means:", sil_kmeans_avg, "\n")
##
## Índice de Silhouette promedio para k-means: 0.2728741
Agrupar las propiedades residenciales en segmentos homogéneos con características similares para entender las dinámicas de las ofertas específicas en diferentes partes de la ciudad y en diferentes estratos socioeconómicos.
Primero, se realiza la normalización de las variables para asegurarnos de que todas las variables estén en la misma escala, como en el ejemplo visto en clase. Utilizando scale para aplicar la fórmula de z donde al valor de la variable se le resta la media y esto se divide en la desviación estándar.
# Estandarización de variables
vivienda_std <- scale(vivienda_completed[, c("preciom", "areaconst", "banios", "habitaciones", "longitud", "latitud")])
vivienda_std <- as.data.frame(vivienda_std)
Antes de aplicar el K-Means, se utiliza PCA para reducir la dimensionalidad y poder visualizar mejor los datos. Esto también ayuda a mejorar la eficiencia del algoritmo de clustering.
# Aplicar PCA
pca_result <- prcomp(vivienda_std, center = TRUE, scale. = TRUE)
# Mostrar resumen del PCA
summary(pca_result)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 1.6791 1.1117 0.8994 0.7809 0.57594 0.44074
## Proportion of Variance 0.4699 0.2060 0.1348 0.1016 0.05528 0.03238
## Cumulative Proportion 0.4699 0.6759 0.8107 0.9123 0.96762 1.00000
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 1.6790 1.1115 0.8996 0.7807 0.57659 0.44079
## Proportion of Variance 0.4698 0.2059 0.1349 0.1016 0.05541 0.03238
## Cumulative Proportion 0.4698 0.6757 0.8106 0.9122 0.96762 1.00000
# Extraer las dos primeras componentes principales
pca_data <- data.frame(pca_result$x[, 1:2]) # Tomamos solo las dos primeras componentes
El siguiente paso es calcular la matriz de distancias entre las viviendas. Se puede usar la distancia Euclidiana, Manhattan o Minkowski:
# Calcular la matriz de distancias
dist_matrix <- dist(pca_data, method = "euclidean")
###Clustering Jerárquico
Para obtener los clústeres de las propiedades, realizamos el análisis de conglomerados utilizando clustering jerárquico. Generamos un dendrograma para visualizar cómo se agrupan las propiedades en función de la distancia euclidiana.
# Aplicar clustering jerárquico
hc_vivienda <- hclust(dist_matrix, method = "complete")
# Graficar el dendrograma
plot(hc_vivienda, cex = 0.6, main = "Dendrograma de Viviendas", las = 1, ylab = "Distancia Euclidiana", xlab = "Viviendas",
col = "blue")
A partir del dendrograma, seleccionamos el número óptimo de clústeres visualmente, evaluamos varios valores de k con el índice de Silhouette, y determinamos cuál es el número de clústeres que mejor segmenta las viviendas.
# Probar diferentes valores de k y calcular el índice de Silhouette
silhouettes <- numeric(9) # Creamos un vector con 9 elementos para almacenar los resultados
for (k in 2:10) {
clusters <- cutree(hc_vivienda, k = k)
sil <- silhouette(clusters, dist_matrix)
silhouettes[k - 1] <- mean(sil[, 3]) # Promedio del índice Silhouette
}
# Mostrar el índice de Silhouette para cada k
silhouette_results <- data.frame(K = 2:10, Silhouette = silhouettes)
print(silhouette_results)
## K Silhouette
## 1 2 0.4703773
## 2 3 0.3235230
## 3 4 0.3221288
## 4 5 0.3139717
## 5 6 0.3611659
## 6 7 0.3496618
## 7 8 0.3328302
## 8 9 0.3297200
## 9 10 0.3363170
# Seleccionar el mejor k
best_k <- 3#silhouette_results$K[which.max(silhouette_results$Silhouette)]
cat("El mejor número de clústeres (k) según el índice de Silhouette es:", best_k, "\n")
## El mejor número de clústeres (k) según el índice de Silhouette es: 3
Se usa el valor óptimo de k encontrado y aplicamos el algoritmo de K-Means en las dos primeras componentes principales generadas por PCA. Posteriormente, asignamos los clústeres a las viviendas y visualizamos los resultados.
# Aplicar K-Means con el mejor número de clústeres
set.seed(123)
kmeans_result <- kmeans(pca_data, centers = best_k, nstart = 25)
# Asignar los clústeres a los datos
vivienda_completed$KMeans_Cluster <- as.factor(kmeans_result$cluster)
# Visualización de los clústeres
ggplot(vivienda_completed, aes(x = preciom, y = areaconst, color = KMeans_Cluster)) +
geom_point(size = 4, alpha = 0.7) +
scale_color_brewer(palette = "Set1") +
theme_classic() +
labs(title = "Clústeres de Viviendas (k-means)", color = "Clúster")
Finalmente, se calcula el índice de Silhouette para evaluar la calidad del agrupamiento. Un valor cercano a 1 indica que los clústeres están bien definidos.
# Cálculo del índice de Silhouette para K-Means
sil_kmeans <- silhouette(kmeans_result$cluster, dist_matrix)
sil_kmeans_avg <- mean(sil_kmeans[, 3])
cat("\nÍndice de Silhouette promedio para k-means:", sil_kmeans_avg, "\n")
##
## Índice de Silhouette promedio para k-means: 0.4284284
Examinar la relación entre las variables categóricas (tipo de vivienda, zona y barrio), para identificar patrones de comportamiento de la oferta en mercado inmobiliario.
En primer lugar, debemos asegurarnos de que las variables tipo_vivienda, zona y estrato estén en formato de factor, dado a que son las variables con las que evaluaremos la correspondencia.
# Asegurarnos de que las variables estén como factores
vivienda_completed$tipo <- as.factor(vivienda_completed$tipo)
vivienda_completed$zona <- as.factor(vivienda_completed$zona)
vivienda_completed$estrato <- as.factor(vivienda_completed$estrato)
Dado que el análisis de correspondencia es sobre tablas 2D, debemos crear una tabla cruzada para dos de las variables, por ejemplo, zona y estrato, y luego hacer un análisis de correspondencia para ver cómo se relacionan con tipo_vivienda.
# Creo una tabla cruzada entre Zona y Estrato
tabla <- table(vivienda_completed$zona, vivienda_completed$estrato)
# tabla cruzada
print(tabla)
##
## 3 4 5 6
## 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
La tabla muestra que:
En la “Zona Centro”, hay 105 registros con estrato 3, 14 con estrato 4, 4 con estrato 5 y 1 con estarto 6. En la “Zona Norte”, hay 572 registros con estrato 3, 407 con estrato 4, etc.
Se realiza la prueba de chi-cuadrado para verificar si hay una relación significativa entre zona y estrato.
# Realizar prueba de chi-cuadrado entre Zona y Estrato
chisq.test(tabla)
##
## Pearson's Chi-squared test
##
## data: tabla
## X-squared = 3830.4, df = 12, p-value < 2.2e-16
Dado que el valor p es mucho menor que el umbral de significancia común de 0.05, rechazamos la hipótesis nula, lo que significa que hay una relación estadísticamente significativa entre “Zona” y “Estrato”.
Las variables “Zona” y “Estrato”, por tanto, están asociadas entre sí, es decir, la distribución del estrato varía significativamente según la zona en este conjunto de datos.
Ahora se realiza el análisis de correspondencia con FactoMineR:
# Análisis de correspondencia
library(FactoMineR)
resultados_ac <- CA(tabla)
# Ver los resultados
summary(resultados_ac)
##
## Call:
## CA(X = tabla)
##
## The chi square of independence between the two variables is equal to 3830.435 (p-value = 0 ).
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3
## Variance 0.322 0.127 0.011
## % of var. 69.966 27.680 2.354
## Cumulative % of var. 69.966 97.646 100.000
##
## Rows
## Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2
## Zona Centro | 47.079 | 1.725 13.761 0.942 | 0.364 1.547 0.042 |
## Zona Norte | 46.762 | 0.390 10.887 0.750 | -0.147 3.920 0.107 |
## Zona Oeste | 135.034 | -0.569 14.476 0.345 | 0.783 69.204 0.653 |
## Zona Oriente | 184.564 | 2.015 53.171 0.928 | 0.537 9.563 0.066 |
## Zona Sur | 47.004 | -0.209 7.704 0.528 | -0.188 15.767 0.428 |
## Dim.3 ctr cos2
## Zona Centro 0.228 7.148 0.016 |
## Zona Norte -0.170 61.735 0.143 |
## Zona Oeste -0.037 1.820 0.001 |
## Zona Oriente 0.160 10.006 0.006 |
## Zona Sur 0.061 19.291 0.044 |
##
## Columns
## Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2
## 3 | 253.402 | 1.187 76.333 0.970 | 0.207 5.851 0.029 |
## 4 | 47.744 | -0.154 1.895 0.128 | -0.380 28.966 0.773 |
## 5 | 25.471 | -0.132 1.796 0.227 | -0.204 10.824 0.542 |
## 6 | 133.827 | -0.519 19.976 0.481 | 0.539 54.359 0.518 |
## Dim.3 ctr cos2
## 3 0.015 0.350 0.000 |
## 4 0.136 43.547 0.099 |
## 5 -0.133 54.323 0.231 |
## 6 0.028 1.780 0.001 |
Las dimensiones (Dim.1, Dim.2, Dim.3) indican la variabilidad explicada en el análisis y muestran cómo las categorías de las variables se distribuyen en este espacio multidimensional.
Dim.1 (Iner*1000 = 253.402): La primera dimensión explica el 76.33% de la variabilidad en los datos.
Las cos2 para esta dimensión son altas, lo que significa que la mayor parte de la variabilidad está siendo explicada por esta dimensión.
Dim.2 (Iner*1000 = 47.744): Explica solo el 1.90% de la variabilidad en los datos, pero las categorías están distribuidas en ella de manera significativa.
Sin embargo, puede ser útil dependiendo de la interpretación que busques.
En cuanto a contribuciones, vemos que la categoría “Zona Centro (3)” tiene una contribución notablemente alta en Dim.1 (76.33%).
En la dimensión 1, las categorías tienen un cos2 alto, indicando que se encuentran bien representadas en esta dimensión.
En conclusión, se puede interpretar que:
Dimensión 1 (Principal) tiene la mayor influencia en el análisis, lo que sugiere que la relación entre “Zona” y “Estrato” se expresa principalmente a través de esta dimensión.
Las categorías con alta contribución en Dimensión 1 probablemente están más separadas en el espacio de correspondencia y son las más relevantes para el análisis.
La dimensión 2 puede capturar otros matices menores en la relación entre las variables, aunque su contribución a la variabilidad total es más pequeña.
# Visualización de los resultados del análisis de correspondencia
library(factoextra)
fviz_ca_biplot(resultados_ac, repel = TRUE, ggtheme = theme_minimal()) +
ggtitle("Análisis de Correspondencia: Zona vs Estrato") +
theme(legend.position = "bottom")
Agregar el tipo de vivienda en la visualización es excelente para ver si existe alguna relación entre el tipo de vivienda y la ubicación en las diferentes zonas y estratos. Se puede hacerlmediante una visualización que combine los resultados del análisis de correspondencia (CA) con el tipo de vivienda como una variable adicional.
Se grafican las dimensiones del análisis de correspondencia y colorean los puntos según el tipo de vivienda para ver si existe algún patrón en cómo se distribuyen. Usaremos las coordenadas de las filas (zonas y estratos) y luego agregamos los puntos correspondientes al tipo de vivienda.
# Análisis de Correspondencia (CA)
resultados_ac <- CA(tabla)
# Visualización del Análisis de Correspondencia
fviz_ca_biplot(resultados_ac,
axes = c(1, 2), # Visualización de las primeras dos dimensiones
col.row = "blue", # Color para las filas (zonas/estratos)
col.col = "red", # Color para las columnas (estratos)
label = "none",
addlabels = TRUE,
legend.title = "Categorías"
)
# Agrego los puntos correspondientes al tipo de vivienda
# Se utiliza el tipo de vivienda como factor para colores
vivienda_completed$tipo <- as.factor(vivienda_completed$tipo)
# Agrego los puntos de tipo de vivienda a la visualización:
fviz_ca_biplot(resultados_ac,
axes = c(1, 2),
col.row = "blue",
col.col = "red",
label = "none",
addlabels = TRUE,
legend.title = "Categorías",
pointsize = 3, # Ajusta el tamaño de los puntos
add = TRUE)
# Coordenadas de las filas (zonas y estratos)
coordenadas_filas <- resultados_ac$row$coord
# Ver las coordenadas de las filas
print(coordenadas_filas)
## Dim 1 Dim 2 Dim 3
## Zona Centro 1.7245923 0.3637090 0.2280066
## Zona Norte 0.3898305 -0.1471227 -0.1702893
## Zona Oeste -0.5690714 0.7826088 -0.0370150
## Zona Oriente 2.0148839 0.5374546 0.1603415
## Zona Sur -0.2090141 -0.1880737 0.0606743
# Crear una tabla con las coordenadas de las filas
tabla_filas <- data.frame(Zona_Estrato = rownames(coordenadas_filas), coordenadas_filas)
print(tabla_filas)
## Zona_Estrato Dim.1 Dim.2 Dim.3
## Zona Centro Zona Centro 1.7245923 0.3637090 0.2280066
## Zona Norte Zona Norte 0.3898305 -0.1471227 -0.1702893
## Zona Oeste Zona Oeste -0.5690714 0.7826088 -0.0370150
## Zona Oriente Zona Oriente 2.0148839 0.5374546 0.1603415
## Zona Sur Zona Sur -0.2090141 -0.1880737 0.0606743
Se puede concluír que:
La Zona Centro tiene una coordenada positiva alta en la primera dimensión (1.7246), lo que podría indicar que es una zona que se asocia fuertemente con algún tipo de vivienda en particular, como las casas (si este es el tipo de vivienda que has asignado en ese contexto).
Si las coordenadas de una zona se agrupan de manera similar en las dimensiones, podría sugerir que en esa zona se concentra un tipo de vivienda específico, como ocurre con las zonas Norte o Sur
La Zona Norte tiene una variedad más amplia de valores en las tres dimensiones, lo que puede indicar que contiene una diversidad de estratos (como se ve en la tabla de la prueba de chi-cuadrado).
Zonas como Zona Oriente tienen valores muy concentrados en las dimensiones, lo que podría indicar que esta zona tiene una mayor homogeneidad en cuanto al estrato (por ejemplo, concentrada en un solo estrato).
Se podría explorar si existe algún agrupamiento natural entre los tipos de viviendas en las diferentes zonas o estratos con la realización un análisis de clustering.
Para esto, se puede usar el k-means clustering, que agrupará las viviendas en diferentes clusters basados en sus características (como el tipo de vivienda, zona y estrato).
# Extraigo las variables relevantes para el clustering
variables_cluster <- vivienda_completed[, c("zona", "estrato", "tipo")]
# Verificar si hay valores faltantes (NA) en las variables seleccionadas
sum(is.na(variables_cluster))
## [1] 9
variables_cluster_clean <- na.omit(variables_cluster)
# Conversión de las variables categóricas a factores numéricos
variables_cluster_clean$zona <- as.numeric(variables_cluster_clean$zona)
variables_cluster_clean$estrato <- as.numeric(variables_cluster_clean$estrato)
variables_cluster_clean$tipo <- as.numeric(variables_cluster_clean$tipo)
# Verificar si hay valores NaN o Inf en las columnas
sum(is.nan(variables_cluster_clean))
## [1] 0
sum(sapply(variables_cluster_clean, function(x) any(is.infinite(x))))
## [1] 0
# Estandarizar las variables para evitar que algunas dominen sobre otras
variables_cluster_scaled <- scale(variables_cluster_clean)
# Realizar el clustering k-means
set.seed(123) # Para asegurar reproducibilidad
clustering_result <- kmeans(variables_cluster_scaled, centers = 3)
# Añadir los resultados del clustering al dataframe original
vivienda_completed$Cluster <- NA # Inicia la columna con NA
vivienda_completed$Cluster[!is.na(variables_cluster$zona)] <- as.factor(clustering_result$cluster)
# Resultados del clustering
table(vivienda_completed$Cluster)
##
## 1 2 3
## 2244 3430 2645
# Asegúrate de que la columna 'Cluster' sea un factor
vivienda_completed$Cluster <- as.factor(vivienda_completed$Cluster)
# Graficar los resultados del clustering
ggplot(vivienda_completed, aes(x = zona, y = estrato, color = Cluster)) +
geom_point() +
labs(title = "Clustering de Viviendas por Zona y Estrato", x = "Zona", y = "Estrato") +
scale_color_discrete(name = "Clusters") +
theme_minimal()
Con el clustering vemos que las viviendas están agrupadas de manera coherente según características relevantes como la zona, el estrato y el tipo. Es decir, se está reflejando diferencias geográficas, socioeconómicas y/o de tipo de vivienda.
También se interpreta que en cuanto a cantidad de viviendas, tenemos que:
# Crear tablas de contingencia para cada variable (zona, estrato, tipo) y el cluster
table_cluster_zona <- table(vivienda_completed$Cluster, vivienda_completed$zona)
table_cluster_estrato <- table(vivienda_completed$Cluster, vivienda_completed$estrato)
table_cluster_tipo <- table(vivienda_completed$Cluster, vivienda_completed$tipo)
# Ver las tablas
print(table_cluster_zona)
##
## Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
## 1 91 396 110 289 1358
## 2 0 0 0 62 3368
## 3 33 1524 1088 0 0
print(table_cluster_estrato)
##
## 3 4 5 6
## 1 814 718 712 0
## 2 259 1093 1034 1044
## 3 380 318 1004 943
print(table_cluster_tipo)
##
## Apartamento Casa
## 1 0 2244
## 2 2849 581
## 3 2251 394
A partir de esta tabla podemos concluír de cada cluster que:
Zona: Tiene viviendas principalmente en la Zona Sur, pero también en la Zona Centro, Zona Norte, y Zona Oeste. Estrato: Está compuesto por viviendas en estratos 3, 4 y 5, con mayor concentración en estratos medios. Tipo: Son casas en su totalidad.
Conclusión Cluster 1: Cluster con viviendas más variadas en términos de zona y estrato, pero todas son casas.
Zona: Se concentra en la Zona Sur, con una pequeña presencia en la Zona Oriente. Estrato: Este cluster tiene una alta concentración de viviendas de estrato 6, lo que indica que son viviendas de alto estrato. Tipo: La mayoría son apartamentos, con una pequeña cantidad de casas.
Conclusión Cluster 2: Cluster que parece estar compuesto por viviendas de alto estrato en la Zona Sur, siendo predominantemente apartamentos.
Zona: Tiene una alta concentración en Zona Norte y Zona Oeste. Estrato: Principalmente estrato 5, con algunas viviendas en estrato 3. Tipo: Predomina el tipo apartamento, con algunas casas.
Conclusión Cluster 3: Cluster compuesto por viviendas de estrato alto (estrato 5) en la Zona Norte y Zona Oeste, mayormente apartamentos.