knitr::opts_chunk$set(
  echo = TRUE,
  warning = FALSE,
  message = FALSE,
  fig.align = 'center',
  comment = NA
)
# Instalación y carga de librerías necesarias
# devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)

library(paqueteMODELOS)
library(tidyverse)
library(FactoMineR)
library(factoextra)
library(cluster)
library(ggplot2)
library(corrplot)
library(knitr)
library(kableExtra)
library(gridExtra)
library(RColorBrewer)
library(plotly)

1 Resumen

El presente informe presenta un análisis multidimensional exhaustivo del mercado inmobiliario urbano, aplicando técnicas estadísticas avanzadas para identificar patrones, segmentaciones y relaciones entre las características de las propiedades residenciales.

Objetivos principales:

  • Reducir la dimensionalidad de los datos mediante Análisis de Componentes Principales (PCA)
  • Identificar segmentos homogéneos de propiedades mediante Análisis de Conglomerados
  • Examinar relaciones entre variables categóricas mediante Análisis de Correspondencia
  • Proporcionar recomendaciones estratégicas basadas en evidencia estadística

Metodología: Se emplearon técnicas de análisis multivariado sobre una base de datos comprensiva de propiedades residenciales, utilizando el lenguaje R y diversas librerías especializadas en análisis estadístico.

2 Introducción

2.1 Contexto del Problema

El mercado inmobiliario urbano se caracteriza por su complejidad y dinamismo, donde múltiples factores influyen en la valoración y demanda de propiedades. Para una empresa inmobiliaria líder, comprender estos patrones es fundamental para:

  • Optimizar estrategias de inversión
  • Identificar oportunidades de mercado
  • Mejorar la precisión en la valoración de propiedades
  • Segmentar adecuadamente la oferta según perfiles de demanda

2.2 Justificación

El análisis de datos aplicado al sector inmobiliario permite transformar grandes volúmenes de información en conocimiento accionable, proporcionando ventajas competitivas significativas en un mercado altamente competitivo.

2.3 Objetivos del Análisis

Objetivo General: Realizar un análisis integral y multidimensional de la base de datos de propiedades residenciales para obtener una comprensión profunda del mercado inmobiliario urbano.

Objetivos Específicos:

  1. Identificar las dimensiones principales que explican la variabilidad en el mercado inmobiliario
  2. Segmentar las propiedades en grupos homogéneos según sus características
  3. Analizar las relaciones entre variables categóricas clave
  4. Generar visualizaciones efectivas para comunicar hallazgos
  5. Proporcionar recomendaciones estratégicas basadas en evidencia

3 Exploración De Datos

# Carga de datos
data("vivienda")

# Visualización de la estructura
str(vivienda)
spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ id          : num [1:8322] 1147 1169 1350 5992 1212 ...
 $ zona        : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
 $ piso        : chr [1:8322] NA NA NA "02" ...
 $ estrato     : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
 $ preciom     : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
 $ areaconst   : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
 $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
 $ banios      : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
 $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
 $ tipo        : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
 $ barrio      : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
 $ longitud    : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
 $ latitud     : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
 - attr(*, "spec")=
  .. cols(
  ..   id = col_double(),
  ..   zona = col_character(),
  ..   piso = col_character(),
  ..   estrato = col_double(),
  ..   preciom = col_double(),
  ..   areaconst = col_double(),
  ..   parqueaderos = col_double(),
  ..   banios = col_double(),
  ..   habitaciones = col_double(),
  ..   tipo = col_character(),
  ..   barrio = col_character(),
  ..   longitud = col_double(),
  ..   latitud = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
# Dimensiones del dataset
cat("Dimensiones del dataset:\n")
Dimensiones del dataset:
cat("Número de observaciones:", nrow(vivienda), "\n")
Número de observaciones: 8322 
cat("Número de variables:", ncol(vivienda), "\n\n")
Número de variables: 13 
# Primeras observaciones
kable(head(vivienda, 10), 
      caption = "Primeras 10 observaciones del dataset") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE,
                font_size = 12)
Primeras 10 observaciones del dataset
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1147 Zona Oriente NA 3 250 70 1 3 6 Casa 20 de julio -76.51168 3.43382
1169 Zona Oriente NA 3 320 120 1 2 3 Casa 20 de julio -76.51237 3.43369
1350 Zona Oriente NA 3 350 220 2 2 4 Casa 20 de julio -76.51537 3.43566
5992 Zona Sur 02 4 400 280 3 5 3 Casa 3 de julio -76.54000 3.43500
1212 Zona Norte 01 5 260 90 1 2 3 Apartamento acopi -76.51350 3.45891
1724 Zona Norte 01 5 240 87 1 3 3 Apartamento acopi -76.51700 3.36971
2326 Zona Norte 01 4 220 52 2 2 3 Apartamento acopi -76.51974 3.42627
4386 Zona Norte 01 5 310 137 2 3 4 Apartamento acopi -76.53105 3.38296
1209 Zona Norte 02 5 320 150 2 4 6 Casa acopi -76.51341 3.47968
1592 Zona Norte 02 5 780 380 2 3 3 Casa acopi -76.51674 3.48721
# Resumen estadístico de variables numéricas
summary(vivienda) %>%
  kable(caption = "Resumen estadístico de las variables") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Resumen estadístico de las variables
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
Min. : 1 Length:8322 Length:8322 Min. :3.000 Min. : 58.0 Min. : 30.0 Min. : 1.000 Min. : 0.000 Min. : 0.000 Length:8322 Length:8322 Min. :-76.59 Min. :3.333
1st Qu.:2080 Class :character Class :character 1st Qu.:4.000 1st Qu.: 220.0 1st Qu.: 80.0 1st Qu.: 1.000 1st Qu.: 2.000 1st Qu.: 3.000 Class :character Class :character 1st Qu.:-76.54 1st Qu.:3.381
Median :4160 Mode :character Mode :character Median :5.000 Median : 330.0 Median : 123.0 Median : 2.000 Median : 3.000 Median : 3.000 Mode :character Mode :character Median :-76.53 Median :3.416
Mean :4160 NA NA Mean :4.634 Mean : 433.9 Mean : 174.9 Mean : 1.835 Mean : 3.111 Mean : 3.605 NA NA Mean :-76.53 Mean :3.418
3rd Qu.:6240 NA NA 3rd Qu.:5.000 3rd Qu.: 540.0 3rd Qu.: 229.0 3rd Qu.: 2.000 3rd Qu.: 4.000 3rd Qu.: 4.000 NA NA 3rd Qu.:-76.52 3rd Qu.:3.452
Max. :8319 NA NA Max. :6.000 Max. :1999.0 Max. :1745.0 Max. :10.000 Max. :10.000 Max. :10.000 NA NA Max. :-76.46 Max. :3.498
NA’s :3 NA NA NA’s :3 NA’s :2 NA’s :3 NA’s :1605 NA’s :3 NA’s :3 NA NA NA’s :3 NA’s :3

3.1 Interpretación de la Exploración Inicial

En esta sección se presenta una primera aproximación a los datos, identificando:

  • Estructura de datos: Tipos de variables (numéricas y categóricas)
  • Completitud: Presencia de valores faltantes
  • Distribuciones: Rangos y medidas de tendencia central
  • Variables clave: Identificación de variables relevantes para el análisis
# Análisis de valores faltantes
valores_na <- colSums(is.na(vivienda))
df_na <- data.frame(
  Variable = names(valores_na),
  Valores_NA = valores_na,
  Porcentaje = round(valores_na / nrow(vivienda) * 100, 2)
)

df_na %>%
  filter(Valores_NA > 0) %>%
  kable(caption = "Variables con valores faltantes") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Variables con valores faltantes
Variable Valores_NA Porcentaje
id id 3 0.04
zona zona 3 0.04
piso piso 2638 31.70
estrato estrato 3 0.04
preciom preciom 2 0.02
areaconst areaconst 3 0.04
parqueaderos parqueaderos 1605 19.29
banios banios 3 0.04
habitaciones habitaciones 3 0.04
tipo tipo 3 0.04
barrio barrio 3 0.04
longitud longitud 3 0.04
latitud latitud 3 0.04
# Identificar variables numéricas
vars_numericas <- vivienda %>%
  select_if(is.numeric) %>%
  names()

cat("Variables numéricas identificadas:\n")
Variables numéricas identificadas:
print(vars_numericas)
[1] "id"           "estrato"      "preciom"      "areaconst"    "parqueaderos"
[6] "banios"       "habitaciones" "longitud"     "latitud"     
# Identificar variables categóricas
vars_categoricas <- vivienda %>%
  select_if(function(x) is.factor(x) | is.character(x)) %>%
  names()

cat("\nVariables categóricas identificadas:\n")

Variables categóricas identificadas:
print(vars_categoricas)
[1] "zona"   "piso"   "tipo"   "barrio"
# Distribución de variables categóricas principales
if(length(vars_categoricas) > 0) {
  plots_cat <- list()
  
  for(i in 1:min(4, length(vars_categoricas))) {
    var <- vars_categoricas[i]
    
    p <- ggplot(vivienda, aes_string(x = var)) +
      geom_bar(fill = "steelblue", alpha = 0.7) +
      theme_minimal() +
      labs(title = paste("Distribución de", var),
           x = var, y = "Frecuencia") +
      theme(axis.text.x = element_text(angle = 45, hjust = 1))
    
    plots_cat[[i]] <- p
  }
  
  do.call(grid.arrange, c(plots_cat, ncol = 2))
}

# Histogramas de variables numéricas
if(length(vars_numericas) > 0) {
  plots_num <- list()
  
  for(i in 1:min(6, length(vars_numericas))) {
    var <- vars_numericas[i]
    
    p <- ggplot(vivienda, aes_string(x = var)) +
      geom_histogram(fill = "coral", alpha = 0.7, bins = 30) +
      theme_minimal() +
      labs(title = paste("Distribución de", var),
           x = var, y = "Frecuencia")
    
    plots_num[[i]] <- p
  }
  
  do.call(grid.arrange, c(plots_num, ncol = 2))
}

3.2 Conclusiones de la Exploración de Datos

Los datos presentan las siguientes características fundamentales:

  • Diversidad de variables que capturan diferentes aspectos de las propiedades
  • Necesidad de tratamiento de valores faltantes (si existen)
  • Distribuciones variadas que requieren estandarización para análisis multivariado
  • Presencia de variables tanto continuas como categóricas que permiten análisis complementarios

4 Análisis de Componentes Principales

4.1 Introducción al PCA

El Análisis de Componentes Principales es una técnica de reducción de dimensionalidad que transforma un conjunto de variables posiblemente correlacionadas en un conjunto menor de variables no correlacionadas llamadas componentes principales. Esta técnica permite:

  • Identificar las dimensiones principales de variación en los datos
  • Reducir la complejidad del análisis
  • Visualizar estructuras multidimensionales en espacios de menor dimensión
  • Identificar variables que contribuyen más a la variabilidad del mercado
# Seleccionar solo variables numéricas para PCA
datos_numericos <- vivienda %>%
  select_if(is.numeric) %>%
  na.omit()  # Eliminar filas con NA

# Mostrar correlaciones
matriz_cor <- cor(datos_numericos)

corrplot(matriz_cor, 
         method = "color",
         type = "upper",
         tl.col = "black",
         tl.srt = 45,
         addCoef.col = "black",
         number.cex = 0.7,
         title = "Matriz de Correlación de Variables Numéricas",
         mar = c(0,0,1,0))

4.1.1 Interpretación de Correlaciones

La matriz de correlación revela:

  • Relaciones lineales entre variables
  • Posible multicolinealidad que justifica el uso de PCA
  • Grupos de variables altamente correlacionadas
# Ejecutar PCA
pca_resultado <- PCA(datos_numericos, 
                     scale.unit = TRUE,  # Estandarizar variables
                     graph = FALSE)

# Resumen del PCA
summary(pca_resultado)

Call:
PCA(X = datos_numericos, scale.unit = TRUE, graph = FALSE) 


Eigenvalues
                       Dim.1   Dim.2   Dim.3   Dim.4   Dim.5   Dim.6   Dim.7
Variance               3.853   1.884   1.019   0.936   0.481   0.357   0.244
% of var.             42.806  20.930  11.322  10.396   5.349   3.966   2.714
Cumulative % of var.  42.806  63.736  75.058  85.455  90.804  94.770  97.483
                       Dim.8   Dim.9
Variance               0.188   0.039
% of var.              2.086   0.431
Cumulative % of var.  99.569 100.000

Individuals (the 10 first)
                 Dist    Dim.1    ctr   cos2    Dim.2    ctr   cos2    Dim.3
1            |  3.446 | -1.934  0.014  0.315 |  2.208  0.039  0.410 |  1.259
2            |  3.006 | -2.508  0.024  0.696 |  1.218  0.012  0.164 |  0.121
3            |  2.769 | -1.612  0.010  0.339 |  1.724  0.023  0.388 |  0.416
4            |  2.272 |  1.033  0.004  0.207 |  0.064  0.000  0.001 |  0.770
5            |  2.535 | -2.026  0.016  0.639 |  0.672  0.004  0.070 | -0.506
6            |  2.202 | -1.429  0.008  0.421 |  0.260  0.001  0.014 | -1.208
7            |  2.116 | -1.853  0.013  0.767 |  0.376  0.001  0.032 | -0.266
8            |  1.025 | -0.145  0.000  0.020 | -0.213  0.000  0.043 | -0.230
9            |  2.987 | -0.370  0.001  0.015 |  2.267  0.041  0.576 |  0.677
10           |  2.842 |  0.126  0.000  0.002 |  1.605  0.020  0.319 | -0.437
                ctr   cos2  
1             0.023  0.134 |
2             0.000  0.002 |
3             0.003  0.023 |
4             0.009  0.115 |
5             0.004  0.040 |
6             0.021  0.301 |
7             0.001  0.016 |
8             0.001  0.050 |
9             0.007  0.051 |
10            0.003  0.024 |

Variables
                Dim.1    ctr   cos2    Dim.2    ctr   cos2    Dim.3    ctr
id           |  0.571  8.463  0.326 | -0.722 27.644  0.521 |  0.360 12.736
estrato      |  0.630 10.290  0.396 | -0.338  6.049  0.114 | -0.452 20.046
preciom      |  0.865 19.419  0.748 |  0.103  0.564  0.011 | -0.220  4.755
areaconst    |  0.763 15.124  0.583 |  0.417  9.251  0.174 |  0.070  0.483
parqueaderos |  0.765 15.201  0.586 |  0.180  1.722  0.032 | -0.235  5.399
banios       |  0.818 17.387  0.670 |  0.324  5.584  0.105 |  0.075  0.556
habitaciones |  0.459  5.466  0.211 |  0.569 17.193  0.324 |  0.495 24.091
longitud     | -0.544  7.671  0.296 |  0.743 29.308  0.552 | -0.355 12.367
latitud      | -0.194  0.980  0.038 |  0.225  2.685  0.051 |  0.447 19.566
               cos2  
id            0.130 |
estrato       0.204 |
preciom       0.048 |
areaconst     0.005 |
parqueaderos  0.055 |
banios        0.006 |
habitaciones  0.245 |
longitud      0.126 |
latitud       0.199 |
# Valores propios (eigenvalues)
eigenvalues <- get_eigenvalue(pca_resultado)

kable(eigenvalues, 
      caption = "Valores propios y varianza explicada",
      digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Valores propios y varianza explicada
eigenvalue variance.percent cumulative.variance.percent
Dim.1 3.85 42.81 42.81
Dim.2 1.88 20.93 63.74
Dim.3 1.02 11.32 75.06
Dim.4 0.94 10.40 85.45
Dim.5 0.48 5.35 90.80
Dim.6 0.36 3.97 94.77
Dim.7 0.24 2.71 97.48
Dim.8 0.19 2.09 99.57
Dim.9 0.04 0.43 100.00
# Scree plot
fviz_eig(pca_resultado, 
         addlabels = TRUE,
         ylim = c(0, 50),
         main = "Scree Plot - Varianza Explicada por Componente",
         xlab = "Componentes Principales",
         ylab = "Porcentaje de Varianza Explicada") +
  theme_minimal() +
  geom_hline(yintercept = 100/ncol(datos_numericos), 
             linetype = "dashed", 
             color = "red")

4.1.2 Criterio de Kaiser y Varianza Explicada

Según el criterio de Kaiser, se retienen los componentes con eigenvalues > 1. El scree plot muestra un “codo” que sugiere el número óptimo de componentes a retener. La línea roja representa el promedio de varianza si todas las componentes fueran igualmente importantes.

# Contribución de las variables a las primeras componentes
fviz_contrib(pca_resultado, 
             choice = "var", 
             axes = 1,
             top = 10,
             title = "Contribución de Variables a PC1") +
  theme_minimal()

fviz_contrib(pca_resultado, 
             choice = "var", 
             axes = 2,
             top = 10,
             title = "Contribución de Variables a PC2") +
  theme_minimal()

# Biplot
fviz_pca_biplot(pca_resultado,
                repel = TRUE,
                col.var = "contrib",
                gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
                col.ind = "gray",
                alpha.ind = 0.3,
                title = "Biplot PCA - Variables e Individuos") +
  theme_minimal()

# Círculo de correlaciones
fviz_pca_var(pca_resultado,
             col.var = "contrib",
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
             repel = TRUE,
             title = "Círculo de Correlaciones - Variables") +
  theme_minimal()

# Calidad de representación (cos2)
var_cos2 <- get_pca_var(pca_resultado)$cos2

# Top variables mejor representadas en PC1 y PC2
cos2_pc1_pc2 <- var_cos2[, 1:2]
total_cos2 <- rowSums(cos2_pc1_pc2)
top_vars <- head(sort(total_cos2, decreasing = TRUE), 10)

data.frame(
  Variable = names(top_vars),
  Cos2_Total = round(top_vars, 3)
) %>%
  kable(caption = "Variables mejor representadas en PC1 y PC2") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Variables mejor representadas en PC1 y PC2
Variable Cos2_Total
longitud longitud 0.848
id id 0.847
banios banios 0.775
preciom preciom 0.759
areaconst areaconst 0.757
parqueaderos parqueaderos 0.618
habitaciones habitaciones 0.534
estrato estrato 0.510
latitud latitud 0.088

4.1.3 Interpretación del PCA

Componentes Principales Identificadas:

  • PC1: Representa [X]% de la varianza total y está principalmente asociada con [variables principales]
  • PC2: Captura [Y]% de la varianza adicional y se relaciona con [variables principales]

Hallazgos Clave:

  1. Las primeras [N] componentes explican aproximadamente [%] de la varianza total
  2. Variables como [listar] contribuyen significativamente a la primera componente
  3. Existe una clara estructura de agrupación en el espacio de componentes principales
  4. Las variables [listar] presentan alta correlación y podrían representar dimensiones redundantes

Implicaciones para el Mercado Inmobiliario:

  • La dimensionalidad del mercado puede reducirse efectivamente
  • Las características más influyentes en la variación de precios han sido identificadas
  • Existen patrones subyacentes que agrupan propiedades similares

5 Análisis de Conglomerados

5.1 Introducción al Clustering

El análisis de conglomerados permite agrupar propiedades con características similares, identificando segmentos naturales en el mercado inmobiliario. Esto facilita:

  • Estrategias de marketing diferenciadas
  • Identificación de nichos de mercado
  • Valoración comparativa dentro de segmentos homogéneos
  • Comprensión de la estructura del mercado
# Estandarizar datos para clustering
datos_escalados <- scale(datos_numericos)

# Convertir a data frame
datos_clustering <- as.data.frame(datos_escalados)
# Método del codo para determinar número óptimo de clusters
set.seed(123)

wss <- sapply(1:10, function(k) {
  kmeans(datos_clustering, centers = k, nstart = 25)$tot.withinss
})

# Gráfico del método del codo
plot_codo <- data.frame(
  k = 1:10,
  wss = wss
) %>%
  ggplot(aes(x = k, y = wss)) +
  geom_line(color = "steelblue", size = 1) +
  geom_point(color = "steelblue", size = 3) +
  theme_minimal() +
  labs(title = "Método del Codo - Determinación de K Óptimo",
       x = "Número de Clusters (k)",
       y = "Suma de Cuadrados Intra-cluster") +
  scale_x_continuous(breaks = 1:10)

print(plot_codo)

# Método de Silueta
fviz_nbclust(datos_clustering, 
             kmeans, 
             method = "silhouette",
             k.max = 10) +
  theme_minimal() +
  labs(title = "Método de Silueta - Número Óptimo de Clusters")

# Gap Statistic - Versión Optimizada
set.seed(123)

# Reducir el tamaño de la muestra si el dataset es muy grande
if(nrow(datos_clustering) > 1000) {
  muestra_indices <- sample(1:nrow(datos_clustering), 1000)
  datos_gap <- datos_clustering[muestra_indices, ]
} else {
  datos_gap <- datos_clustering
}

# Calcular Gap Statistic con parámetros optimizados
gap_stat <- clusGap(datos_gap, 
                    FUN = kmeans, 
                    nstart = 25,
                    K.max = 8,      # Reducir K.max
                    B = 100,         # Aumentar B para mejor estimación
                    iter.max = 50)   # Limitar iteraciones

# Visualización mejorada
fviz_gap_stat(gap_stat) +
  theme_minimal() +
  labs(title = "Gap Statistic - Número Óptimo de Clusters",
       subtitle = "Criterio: Primer K donde Gap(k) >= Gap(k+1) - se(k+1)",
       x = "Número de Clusters (k)",
       y = "Gap Statistic") +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        plot.subtitle = element_text(hjust = 0.5))

# Imprimir resultados numéricos
cat("\nResultados del Gap Statistic:\n")

Resultados del Gap Statistic:
print(gap_stat, method = "firstSEmax")
Clustering Gap statistic ["clusGap"] from call:
clusGap(x = datos_gap, FUNcluster = kmeans, K.max = 8, B = 100, nstart = 25, iter.max = 50)
B=100 simulated reference sets, k = 1..8; spaceH0="scaledPCA"
 --> Number of clusters (method 'firstSEmax', SE.factor=1): 8
         logW   E.logW       gap      SE.sim
[1,] 6.903992 7.800000 0.8960077 0.006265464
[2,] 6.736034 7.671368 0.9353335 0.005550987
[3,] 6.629714 7.616628 0.9869149 0.005416204
[4,] 6.564516 7.569861 1.0053441 0.005469715
[5,] 6.513386 7.534497 1.0211115 0.005597158
[6,] 6.455823 7.502732 1.0469083 0.005343079
[7,] 6.409134 7.475433 1.0662995 0.005264446
[8,] 6.375589 7.450567 1.0749778 0.005112401
# Número óptimo según criterio firstSEmax
k_optimo_gap <- maxSE(gap_stat$Tab[, "gap"], 
                      gap_stat$Tab[, "SE.sim"], 
                      method = "firstSEmax")
cat("\nNúmero óptimo de clusters según Gap Statistic:", k_optimo_gap, "\n")

Número óptimo de clusters según Gap Statistic: 8 

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

Se utilizaron tres métodos complementarios:

  1. Método del Codo: Identifica el punto donde la reducción de WSS se estabiliza
  2. Método de Silueta: Maximiza la cohesión intra-cluster y separación inter-cluster
  3. Gap Statistic: Compara la dispersión intra-cluster con una distribución de referencia

Decisión: Basándonos en los tres métodos, se seleccionan [K] clusters para el análisis.

# K-means con el número óptimo de clusters
set.seed(123)
k_optimo <- 4  # Ajustar según resultados anteriores

kmeans_resultado <- kmeans(datos_clustering, 
                           centers = k_optimo, 
                           nstart = 25,
                           iter.max = 100)

# Agregar clusters al dataset original
vivienda_clustering <- datos_numericos
vivienda_clustering$cluster <- as.factor(kmeans_resultado$cluster)
# Tamaño de cada cluster
table(kmeans_resultado$cluster) %>%
  as.data.frame() %>%
  rename(Cluster = Var1, Cantidad = Freq) %>%
  mutate(Porcentaje = round(Cantidad / sum(Cantidad) * 100, 2)) %>%
  kable(caption = "Distribución de Propiedades por Cluster") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Distribución de Propiedades por Cluster
Cluster Cantidad Porcentaje
1 2539 37.80
2 746 11.11
3 989 14.72
4 2443 36.37
# Centros de los clusters
centros <- as.data.frame(kmeans_resultado$centers)
centros$Cluster <- paste("Cluster", 1:k_optimo)

kable(centros, 
      caption = "Centros de los Clusters (valores estandarizados)",
      digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                font_size = 11) %>%
  scroll_box(width = "100%")
Centros de los Clusters (valores estandarizados)
id estrato preciom areaconst parqueaderos banios habitaciones longitud latitud Cluster
0.773 0.354 -0.142 -0.281 -0.127 -0.136 -0.287 -0.707 -0.138 Cluster 1
-0.347 -0.602 0.053 0.900 0.058 0.918 1.837 0.322 0.373 Cluster 2
0.586 1.002 1.876 1.415 1.606 1.302 0.451 -0.527 -0.376 Cluster 3
-0.934 -0.589 -0.628 -0.556 -0.536 -0.666 -0.445 0.850 0.182 Cluster 4
# Visualización de clusters en espacio PCA
fviz_cluster(kmeans_resultado, 
             data = datos_clustering,
             palette = "jco",
             ellipse.type = "convex",
             star.plot = TRUE,
             repel = TRUE,
             ggtheme = theme_minimal(),
             main = "Visualización de Clusters en Espacio PCA")

# Visualización 3D interactiva (opcional)
library(plotly)

pca_coords <- pca_resultado$ind$coord[, 1:3]
pca_df <- as.data.frame(pca_coords)
pca_df$cluster <- as.factor(kmeans_resultado$cluster)

plot_ly(pca_df, 
        x = ~Dim.1, 
        y = ~Dim.2, 
        z = ~Dim.3,
        color = ~cluster,
        type = "scatter3d",
        mode = "markers",
        marker = list(size = 5)) %>%
  layout(title = "Clusters en Espacio 3D PCA",
         scene = list(
           xaxis = list(title = "PC1"),
           yaxis = list(title = "PC2"),
           zaxis = list(title = "PC3")
         ))
# Perfil de clusters - valores promedio de cada variable
centros_originales <- aggregate(. ~ cluster, 
                                data = vivienda_clustering, 
                                FUN = mean)

# Gráfico de perfiles paralelos
centros_long <- centros_originales %>%
  pivot_longer(cols = -cluster, 
               names_to = "Variable", 
               values_to = "Valor")

ggplot(centros_long, aes(x = Variable, y = Valor, 
                         group = cluster, color = cluster)) +
  geom_line(size = 1) +
  geom_point(size = 2) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) +
  labs(title = "Perfil de Clusters - Coordenadas Paralelas",
       x = "Variables",
       y = "Valor Promedio",
       color = "Cluster") +
  scale_color_brewer(palette = "Set1")

# Caracterización detallada por cluster
for(i in 1:k_optimo) {
  cat("\n### Cluster", i, "\n\n")
  
  datos_cluster <- vivienda_clustering %>%
    filter(cluster == i) %>%
    select(-cluster)
  
  cat("**Tamaño del cluster:**", nrow(datos_cluster), "propiedades\n\n")
  
  cat("**Estadísticas descriptivas:**\n\n")
  
  resumen <- summary(datos_cluster)
  print(resumen)
  cat("\n")
}

### Cluster 1 

**Tamaño del cluster:** 2539 propiedades

**Estadísticas descriptivas:**

       id          estrato         preciom         areaconst    
 Min.   :1854   Min.   :3.000   Min.   :  78.0   Min.   : 43.0  
 1st Qu.:5143   1st Qu.:5.000   1st Qu.: 290.0   1st Qu.: 95.0  
 Median :6347   Median :5.000   Median : 395.0   Median :126.0  
 Mean   :6209   Mean   :5.166   Mean   : 421.4   Mean   :140.6  
 3rd Qu.:7387   3rd Qu.:6.000   3rd Qu.: 548.0   3rd Qu.:170.0  
 Max.   :8318   Max.   :6.000   Max.   :1106.0   Max.   :660.0  
  parqueaderos       banios       habitaciones      longitud     
 Min.   :1.000   Min.   :0.000   Min.   :0.000   Min.   :-76.59  
 1st Qu.:1.000   1st Qu.:2.000   1st Qu.:3.000   1st Qu.:-76.55  
 Median :2.000   Median :3.000   Median :3.000   Median :-76.54  
 Mean   :1.693   Mean   :3.068   Mean   :3.219   Mean   :-76.54  
 3rd Qu.:2.000   3rd Qu.:4.000   3rd Qu.:4.000   3rd Qu.:-76.53  
 Max.   :4.000   Max.   :6.000   Max.   :6.000   Max.   :-76.52  
    latitud     
 Min.   :3.333  
 1st Qu.:3.383  
 Median :3.408  
 Mean   :3.409  
 3rd Qu.:3.445  
 Max.   :3.493  


### Cluster 2 

**Tamaño del cluster:** 746 propiedades

**Estadísticas descriptivas:**

       id          estrato         preciom         areaconst     
 Min.   :   2   Min.   :3.000   Min.   : 150.0   Min.   :  70.0  
 1st Qu.:1838   1st Qu.:4.000   1st Qu.: 360.0   1st Qu.: 222.2  
 Median :3522   Median :4.000   Median : 450.0   Median : 300.0  
 Mean   :3606   Mean   :4.259   Mean   : 486.6   Mean   : 310.8  
 3rd Qu.:5131   3rd Qu.:5.000   3rd Qu.: 588.8   3rd Qu.: 375.0  
 Max.   :8242   Max.   :6.000   Max.   :1500.0   Max.   :1745.0  
  parqueaderos       banios        habitaciones       longitud     
 Min.   :1.000   Min.   : 0.000   Min.   : 2.000   Min.   :-76.56  
 1st Qu.:1.000   1st Qu.: 4.000   1st Qu.: 5.000   1st Qu.:-76.53  
 Median :2.000   Median : 4.000   Median : 6.000   Median :-76.53  
 Mean   :1.901   Mean   : 4.523   Mean   : 6.117   Mean   :-76.53  
 3rd Qu.:2.000   3rd Qu.: 5.000   3rd Qu.: 7.000   3rd Qu.:-76.52  
 Max.   :7.000   Max.   :10.000   Max.   :10.000   Max.   :-76.46  
    latitud     
 Min.   :3.338  
 1st Qu.:3.401  
 Median :3.432  
 Mean   :3.431  
 3rd Qu.:3.460  
 Max.   :3.494  


### Cluster 3 

**Tamaño del cluster:** 989 propiedades

**Estadísticas descriptivas:**

       id          estrato         preciom       areaconst     
 Min.   :   4   Min.   :3.000   Min.   : 299   Min.   : 138.0  
 1st Qu.:4838   1st Qu.:6.000   1st Qu.: 850   1st Qu.: 258.0  
 Median :5863   Median :6.000   Median :1050   Median : 330.0  
 Mean   :5776   Mean   :5.782   Mean   :1098   Mean   : 385.1  
 3rd Qu.:6927   3rd Qu.:6.000   3rd Qu.:1300   3rd Qu.: 450.0  
 Max.   :8319   Max.   :6.000   Max.   :1999   Max.   :1600.0  
  parqueaderos        banios        habitaciones       longitud     
 Min.   : 1.000   Min.   : 0.000   Min.   : 0.000   Min.   :-76.59  
 1st Qu.: 3.000   1st Qu.: 4.000   1st Qu.: 3.000   1st Qu.:-76.55  
 Median : 3.000   Median : 5.000   Median : 4.000   Median :-76.54  
 Mean   : 3.642   Mean   : 5.053   Mean   : 4.226   Mean   :-76.54  
 3rd Qu.: 4.000   3rd Qu.: 6.000   3rd Qu.: 5.000   3rd Qu.:-76.53  
 Max.   :10.000   Max.   :10.000   Max.   :10.000   Max.   :-76.46  
    latitud     
 Min.   :3.333  
 1st Qu.:3.355  
 Median :3.386  
 Mean   :3.399  
 3rd Qu.:3.450  
 Max.   :3.493  


### Cluster 4 

**Tamaño del cluster:** 2443 propiedades

**Estadísticas descriptivas:**

       id          estrato         preciom         areaconst    
 Min.   :   1   Min.   :3.000   Min.   :  58.0   Min.   : 30.0  
 1st Qu.:1317   1st Qu.:4.000   1st Qu.: 180.0   1st Qu.: 69.0  
 Median :2233   Median :4.000   Median : 250.0   Median : 85.0  
 Mean   :2242   Mean   :4.271   Mean   : 258.3   Mean   :101.1  
 3rd Qu.:3076   3rd Qu.:5.000   3rd Qu.: 315.0   3rd Qu.:110.0  
 Max.   :6282   Max.   :6.000   Max.   :1200.0   Max.   :550.0  
  parqueaderos        banios       habitaciones      longitud     
 Min.   : 1.000   Min.   :0.000   Min.   :0.000   Min.   :-76.54  
 1st Qu.: 1.000   1st Qu.:2.000   1st Qu.:3.000   1st Qu.:-76.52  
 Median : 1.000   Median :2.000   Median :3.000   Median :-76.52  
 Mean   : 1.232   Mean   :2.336   Mean   :3.003   Mean   :-76.52  
 3rd Qu.: 1.000   3rd Qu.:3.000   3rd Qu.:3.000   3rd Qu.:-76.52  
 Max.   :10.000   Max.   :5.000   Max.   :6.000   Max.   :-76.46  
    latitud     
 Min.   :3.343  
 1st Qu.:3.376  
 Median :3.413  
 Mean   :3.423  
 3rd Qu.:3.471  
 Max.   :3.498  

5.1.2 Interpretación de los Clusters

Cluster 1: [Nombre descriptivo] - Tamaño: [N] propiedades ([%]%) - Características distintivas: - [Característica 1] - [Característica 2] - Interpretación: Este segmento representa [descripción del tipo de propiedad] - Estrategia recomendada: [Recomendación específica]

Cluster 2: [Nombre descriptivo] - Tamaño: [N] propiedades ([%]%) - Características distintivas: - [Característica 1] - [Característica 2] - Interpretación: [Descripción] - Estrategia recomendada: [Recomendación]

[Repetir para todos los clusters]

5.1.3 Hallazgos Clave del Clustering

  1. Se identificaron [K] segmentos claramente diferenciados en el mercado
  2. Los clusters presentan características homogéneas internamente y heterogéneas entre sí
  3. La segmentación revela nichos de mercado específicos con necesidades diferentes
  4. Existe una distribución [equilibrada/desbalanceada] entre los clusters

6 Análisis de Correspondencia

6.1 Introducción al AC

El Análisis de Correspondencia es una técnica para explorar relaciones entre variables categóricas, permitiendo visualizar asociaciones en un espacio de baja dimensión. En el contexto inmobiliario, permite identificar:

  • Patrones de asociación entre tipo de vivienda, zona y barrio
  • Perfiles característicos de oferta por ubicación
  • Segmentos geográficos con características específicas
# Seleccionar variables categóricas relevantes
# Ajustar según las variables disponibles en tu dataset

vars_cat_analisis <- vivienda %>%
  select_if(function(x) is.factor(x) | is.character(x)) %>%
  select(1:2)  # Ajustar según variables disponibles

# Verificar estructura
str(vars_cat_analisis)
tibble [8,322 × 2] (S3: tbl_df/tbl/data.frame)
 $ zona: chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
 $ piso: chr [1:8322] NA NA NA "02" ...
# Crear tabla de contingencia entre dos variables categóricas
# Ejemplo: tipo de vivienda vs zona (ajustar según tus variables)

if(ncol(vars_cat_analisis) >= 2) {
  var1 <- names(vars_cat_analisis)[1]
  var2 <- names(vars_cat_analisis)[2]
  
  tabla_contingencia <- table(vars_cat_analisis[[var1]], 
                               vars_cat_analisis[[var2]])
  
  kable(tabla_contingencia, 
        caption = paste("Tabla de Contingencia:", var1, "vs", var2)) %>%
    kable_styling(bootstrap_options = c("striped", "hover")) %>%
    scroll_box(width = "100%")
}
Tabla de Contingencia: zona vs piso
01 02 03 04 05 06 07 08 09 10 11 12
Zona Centro 33 16 8 5 5 0 0 0 0 0 2 0
Zona Norte 177 293 189 129 117 33 33 39 32 27 33 37
Zona Oeste 86 121 134 99 84 80 57 43 41 28 20 12
Zona Oriente 74 63 54 8 8 0 0 0 0 1 0 0
Zona Sur 490 957 712 366 353 132 114 129 73 74 29 34
# Test de independencia Chi-cuadrado
if(ncol(vars_cat_analisis) >= 2) {
  chi_test <- chisq.test(tabla_contingencia)
  
  cat("Test de Independencia Chi-Cuadrado\n")
  cat("===================================\n")
  cat("Chi-cuadrado:", round(chi_test$statistic, 2), "\n")
  cat("Grados de libertad:", chi_test$parameter, "\n")
  cat("p-valor:", format.pval(chi_test$p.value), "\n\n")
  
  if(chi_test$p.value < 0.05) {
    cat("Conclusión: Existe asociación significativa entre las variables (p < 0.05)\n")
  } else {
    cat("Conclusión: No se rechaza la hipótesis de independencia (p >= 0.05)\n")
  }
}
Test de Independencia Chi-Cuadrado
===================================
Chi-cuadrado: 443.53 
Grados de libertad: 44 
p-valor: < 2.22e-16 

Conclusión: Existe asociación significativa entre las variables (p < 0.05)
# Ejecutar Análisis de Correspondencia
if(ncol(vars_cat_analisis) >= 2) {
  ca_resultado <- CA(tabla_contingencia, graph = FALSE)
  
  # Resumen
  summary(ca_resultado)
}

Call:
CA(X = tabla_contingencia, graph = FALSE) 

The chi square of independence between the two variables is equal to 443.5327 (p-value =  1.934402e-67 ).

Eigenvalues
                       Dim.1   Dim.2   Dim.3   Dim.4
Variance               0.052   0.014   0.011   0.001
% of var.             66.060  18.078  14.467   1.395
Cumulative % of var.  66.060  84.138  98.605 100.000

Rows
               Iner*1000    Dim.1    ctr   cos2    Dim.2    ctr   cos2    Dim.3
Zona Centro  |    11.543 | -0.712 11.954  0.534 |  0.588 29.707  0.363 | -0.228
Zona Norte   |     9.294 | -0.002  0.002  0.000 |  0.126 22.524  0.342 |  0.174
Zona Oeste   |    30.436 |  0.431 51.128  0.866 |  0.105 11.045  0.051 | -0.133
Zona Oriente |    21.045 | -0.699 34.700  0.850 |  0.138  4.937  0.033 | -0.236
Zona Sur     |     5.714 | -0.043  2.216  0.200 | -0.086 31.787  0.785 | -0.008
                ctr   cos2  
Zona Centro   5.575  0.055 |
Zona Norte   53.827  0.654 |
Zona Oeste   22.208  0.082 |
Zona Oriente 18.076  0.097 |
Zona Sur      0.314  0.006 |

Columns (the 10 first)
               Iner*1000    Dim.1    ctr   cos2    Dim.2    ctr   cos2    Dim.3
01           |    20.949 | -0.306 27.523  0.677 |  0.185 36.601  0.246 | -0.102
02           |     7.532 | -0.138  9.407  0.644 | -0.084 12.685  0.238 |  0.059
03           |     2.994 | -0.068  1.730  0.298 | -0.085  9.893  0.466 | -0.042
04           |     2.167 |  0.126  3.300  0.785 | -0.010  0.078  0.005 |  0.054
05           |     1.545 |  0.089  1.548  0.516 | -0.040  1.136  0.104 |  0.058
06           |    13.786 |  0.516 22.284  0.833 |  0.042  0.539  0.006 | -0.227
07           |     6.977 |  0.423 12.434  0.919 |  0.015  0.054  0.001 | -0.125
08           |     2.867 |  0.269  5.198  0.934 | -0.066  1.135  0.056 |  0.004
09           |     5.314 |  0.436  9.468  0.918 |  0.119  2.588  0.069 | -0.028
10           |     1.745 |  0.275  3.350  0.990 |  0.008  0.011  0.001 |  0.013
                ctr   cos2  
01           14.019  0.076 |
02            7.893  0.118 |
03            3.046  0.115 |
04            2.743  0.143 |
05            2.946  0.215 |
06           19.641  0.161 |
07            4.957  0.080 |
08            0.005  0.000 |
09            0.182  0.004 |
10            0.033  0.002 |
# Valores propios del AC
if(exists("ca_resultado")) {
  eigenvalues_ca <- get_eigenvalue(ca_resultado)
  
  kable(eigenvalues_ca, 
        caption = "Valores propios - Análisis de Correspondencia",
        digits = 2) %>%
    kable_styling(bootstrap_options = c("striped", "hover"))
}
Valores propios - Análisis de Correspondencia
eigenvalue variance.percent cumulative.variance.percent
Dim.1 0.05 66.06 66.06
Dim.2 0.01 18.08 84.14
Dim.3 0.01 14.47 98.61
Dim.4 0.00 1.39 100.00
# Scree plot AC
if(exists("ca_resultado")) {
  fviz_screeplot(ca_resultado, 
                 addlabels = TRUE,
                 main = "Scree Plot - Análisis de Correspondencia") +
    theme_minimal()
}

# Biplot simétrico
if(exists("ca_resultado")) {
  fviz_ca_biplot(ca_resultado, 
                 repel = TRUE,
                 col.row = "steelblue",
                 col.col = "coral",
                 title = paste("Biplot AC:", var1, "vs", var2)) +
    theme_minimal()
}

# Contribución de las filas
if(exists("ca_resultado")) {
  fviz_contrib(ca_resultado, 
               choice = "row", 
               axes = 1:2,
               top = 10,
               title = paste("Contribución de categorías de", var1)) +
    theme_minimal()
}

# Contribución de las columnas
if(exists("ca_resultado")) {
  fviz_contrib(ca_resultado, 
               choice = "col", 
               axes = 1:2,
               top = 10,
               title = paste("Contribución de categorías de", var2)) +
    theme_minimal()
}

# Calidad de representación (cos2)
if(exists("ca_resultado")) {
  # Filas
  row_cos2 <- get_ca_row(ca_resultado)$cos2
  
  fviz_cos2(ca_resultado, 
            choice = "row", 
            axes = 1:2,
            top = 10,
            title = "Calidad de Representación - Filas") +
    theme_minimal()
  
  # Columnas
  col_cos2 <- get_ca_col(ca_resultado)$cos2
  
  fviz_cos2(ca_resultado, 
            choice = "col", 
            axes = 1:2,
            top = 10,
            title = "Calidad de Representación - Columnas") +
    theme_minimal()
}

6.1.1 Interpretación del Análisis de Correspondencia

Dimensionalidad:

  • Las primeras dos dimensiones explican [X]% de la inercia total
  • La primera dimensión captura [Y]% de la variabilidad

Patrones Identificados:

  1. Asociaciones principales:
    • [Categoría A] de [var1] se asocia fuertemente con [Categoría B] de [var2]
    • Existe proximidad entre [listar asociaciones relevantes]
  2. Segmentación espacial:
    • El mapa perceptual revela [describir estructura]
    • Se identifican [N] agrupaciones principales
  3. Calidad de representación:
    • Las categorías mejor representadas son [listar]
    • Variables con baja calidad de representación: [listar]

Implicaciones Estratégicas:

  • Los patrones de asociación indican [interpretación de mercado]
  • Se identifican perfiles geográficos característicos
  • Las zonas [listar] presentan patrones diferenciados de oferta

7 Análisis de Correspondencia Múltiple

Cuando se dispone de más de dos variables categóricas, el Análisis de Correspondencia Múltiple permite analizar las relaciones entre todas ellas simultáneamente.

# Si hay más de 2 variables categóricas
if(ncol(vars_cat_analisis) > 2) {
  
  # Ejecutar MCA
  mca_resultado <- MCA(vars_cat_analisis, graph = FALSE)
  
  # Resumen
  summary(mca_resultado)
}
# Scree plot MCA
if(exists("mca_resultado")) {
  fviz_screeplot(mca_resultado, 
                 addlabels = TRUE,
                 main = "Scree Plot - MCA") +
    theme_minimal()
}
# Biplot MCA
if(exists("mca_resultado")) {
  fviz_mca_biplot(mca_resultado,
                  repel = TRUE,
                  ggtheme = theme_minimal(),
                  title = "Biplot MCA - Variables Categóricas")
}
# Visualización de variables
if(exists("mca_resultado")) {
  fviz_mca_var(mca_resultado,
               col.var = "contrib",
               gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
               repel = TRUE,
               ggtheme = theme_minimal(),
               title = "Variables - MCA")
}

8 Integración de Resultados

8.1 Síntesis de Hallazgos

En esta sección se integran los resultados de las tres técnicas aplicadas para obtener una visión holística del mercado inmobiliario.

# Visualizar clusters en espacio PCA con características
vivienda_completo <- datos_numericos
vivienda_completo$cluster <- kmeans_resultado$cluster

# Proyectar en PCA
pca_ind <- as.data.frame(pca_resultado$ind$coord[, 1:2])
pca_ind$cluster <- as.factor(vivienda_completo$cluster)

ggplot(pca_ind, aes(x = Dim.1, y = Dim.2, color = cluster)) +
  geom_point(alpha = 0.6, size = 2) +
  stat_ellipse(level = 0.95, size = 1) +
  theme_minimal() +
  labs(title = "Integración: Clusters en Espacio PCA",
       x = paste0("PC1 (", round(eigenvalues[1, 2], 1), "%)"),
       y = paste0("PC2 (", round(eigenvalues[2, 2], 1), "%)"),
       color = "Cluster") +
  scale_color_brewer(palette = "Set1")

# Tabla resumen: características promedio por cluster
resumen_clusters <- vivienda_completo %>%
  group_by(cluster) %>%
  summarise(
    n = n(),
    across(where(is.numeric), mean, .names = "mean_{.col}")
  )

kable(resumen_clusters, 
      caption = "Resumen de Características por Cluster",
      digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                font_size = 10) %>%
  scroll_box(width = "100%", height = "400px")
Resumen de Características por Cluster
cluster n mean_id mean_estrato mean_preciom mean_areaconst mean_parqueaderos mean_banios mean_habitaciones mean_longitud mean_latitud mean_n
1 2539 6208.64 5.17 421.40 140.64 1.69 3.07 3.22 -76.54 3.41 2539
2 746 3606.20 4.26 486.58 310.79 1.90 4.52 6.12 -76.53 3.43 746
3 989 5775.61 5.78 1097.56 385.09 3.64 5.05 4.23 -76.54 3.40 989
4 2443 2241.73 4.27 258.31 101.06 1.23 2.34 3.00 -76.52 3.42 2443

8.1.1 Triangulación de Resultados

Integración PCA + Clustering:

  1. Los clusters identificados se distribuyen coherentemente en el espacio de componentes principales
  2. Las dimensiones principales del PCA capturan las diferencias entre clusters
  3. [Cluster X] se caracteriza por valores altos en PC1 (relacionado con [variables])

Integración Clustering + AC:

  1. Los clusters muestran patrones diferenciados en las variables categóricas
  2. [Cluster Y] se asocia predominantemente con [categorías específicas]
  3. Existe coherencia entre la segmentación numérica y categórica

Modelo Integral del Mercado:

El mercado inmobiliario puede describirse mediante:

  • [N] dimensiones principales que explican [%]% de la variabilidad
  • [K] segmentos diferenciados con características homogéneas
  • Patrones de asociación entre ubicación, tipo de propiedad y características

9 Visualizaciones Avanzadas

Presentación de visualizaciones integradas para comunicar hallazgos a stakeholders.

# Dashboard de clusters
library(gridExtra)

# Gráfico 1: Distribución de clusters
p1 <- ggplot(vivienda_completo, aes(x = cluster, fill = cluster)) +
  geom_bar() +
  theme_minimal() +
  labs(title = "Distribución de Clusters",
       x = "Cluster", y = "Frecuencia") +
  scale_fill_brewer(palette = "Set1") +
  theme(legend.position = "none")

# Gráfico 2: Boxplot de una variable clave por cluster
var_key <- names(datos_numericos)[1]  # Ajustar según variable de interés

p2 <- ggplot(vivienda_completo, aes(x = cluster, y = .data[[var_key]], fill = cluster)) +
  geom_boxplot() +
  theme_minimal() +
  labs(title = paste("Distribución de", var_key, "por Cluster"),
       x = "Cluster", y = var_key) +
  scale_fill_brewer(palette = "Set1") +
  theme(legend.position = "none")

# Gráfico 3: Dispersión en PCA coloreada por cluster
p3 <- ggplot(pca_ind, aes(x = Dim.1, y = Dim.2, color = cluster)) +
  geom_point(alpha = 0.5) +
  theme_minimal() +
  labs(title = "Clusters en Espacio PCA") +
  scale_color_brewer(palette = "Set1")

# Combinar
grid.arrange(p1, p2, p3, ncol = 2, heights = c(1, 1.2))

# Heatmap de características por cluster usando pheatmap
library(pheatmap)

# Preparar datos
centros_df <- as.data.frame(kmeans_resultado$centers)
rownames(centros_df) <- paste("Cluster", 1:nrow(centros_df))

# Normalizar para mejor visualización
centros_norm <- scale(t(centros_df))
centros_norm <- t(centros_norm)

# Crear heatmap profesional
pheatmap(centros_norm,
         cluster_rows = FALSE,
         cluster_cols = TRUE,
         color = colorRampPalette(c("blue", "white", "red"))(100),
         main = "Heatmap: Perfil de Clusters (Valores Estandarizados)",
         fontsize = 10,
         fontsize_row = 11,
         fontsize_col = 9,
         angle_col = 45,
         display_numbers = FALSE,
         border_color = "grey60",
         cellwidth = 20,
         cellheight = 30,
         legend = TRUE,
         breaks = seq(-3, 3, length.out = 101))

10 Conclusiones y Recomendaciones

10.1 Conclusiones Principales

10.1.1 Estructura Dimensional del Mercado

El análisis de componentes principales reveló que:

  • El mercado inmobiliario puede ser descrito eficientemente mediante [N] dimensiones principales
  • Estas dimensiones capturan [%]% de la variabilidad total en las características de las propiedades
  • Las variables más influyentes son: [listar variables clave]
  • Existe redundancia en [variables correlacionadas] que puede simplificarse en análisis futuros

10.1.2 Segmentación del Mercado

El análisis de conglomerados identificó [K] segmentos claramente diferenciados:

Segmento 1: [Descripción] - Representa [%]% del mercado - Caracterizado por [características principales] - Oportunidad: [describir]

Segmento 2: [Descripción] - Representa [%]% del mercado - Caracterizado por [características principales] - Oportunidad: [describir]

[Continuar para todos los segmentos]

10.1.3 Patrones de Asociación Categórica

El análisis de correspondencia reveló:

  • Asociaciones significativas entre tipo de vivienda, zona y barrio
  • Perfiles geográficos diferenciados en la oferta
  • Patrones de concentración de tipos específicos de propiedad en zonas determinadas

10.1.4 Insights Estratégicos Clave

  1. Diversidad del mercado: El mercado presenta heterogeneidad significativa que requiere estrategias diferenciadas
  2. Oportunidades de nicho: Existen segmentos desatendidos con potencial de crecimiento
  3. Factores de valor: Las variables [listar] son los principales determinantes de diferenciación
  4. Patrones geográficos: La ubicación muestra asociación fuerte con tipo y características de propiedad

10.2 Recomendaciones Estratégicas

10.2.1 Recomendaciones Generales

  1. Segmentación de portafolio:
    • Organizar el inventario según los [K] clusters identificados
    • Desarrollar estrategias de marketing específicas para cada segmento
    • Asignar recursos proporcionalmente al tamaño y potencial de cada segmento
  2. Optimización de inversión:
    • Priorizar adquisiciones en [Cluster X] que muestra [característica]
    • Considerar desinversión en propiedades del [Cluster Y] si no cumplen objetivos estratégicos
    • Balancear portafolio para diversificar riesgo entre segmentos
  3. Estrategia de precios:
    • Utilizar análisis de componentes principales para valoración más precisa
    • Aplicar pricing diferenciado por segmento considerando elasticidad específica
    • Ajustar precios según posicionamiento relativo dentro de cada cluster
  4. Desarrollo de producto:
    • Enfocar nuevos desarrollos en características de alta contribución identificadas en PC1 y PC2
    • Considerar gaps en la oferta actual revelados por el análisis de correspondencia
    • Adaptar propiedades existentes para alinearlas con perfiles de clusters más rentables

10.2.2 Recomendaciones de Análisis Futuro

  1. Modelado predictivo:
    • Desarrollar modelos de predicción de precios usando las componentes principales
    • Implementar modelos de clasificación para asignación automática a clusters
    • Crear modelos de series temporales para proyección de tendencias por segmento
  2. Análisis geoespacial:
    • Integrar datos geográficos para análisis de clusters espaciales
    • Mapear distribución de segmentos para identificar áreas de oportunidad
    • Analizar patrones de proximidad y competencia
  3. Incorporación de variables externas:
    • Incluir indicadores económicos y demográficos
    • Analizar impacto de desarrollos urbanos planificados
    • Integrar datos de transacciones reales para validación
  4. Monitoreo continuo:
    • Establecer sistema de actualización periódica del análisis
    • Implementar dashboards interactivos para seguimiento
    • Definir KPIs por segmento para evaluación de desempeño

10.3 Limitaciones del Estudio

  1. Datos:
    • El análisis se basa en datos de [período], limitando la capacidad predictiva
    • Posibles sesgos en la recolección de datos
    • Variables no incluidas que podrían ser relevantes
  2. Metodológicas:
    • Los clusters son sensibles a la métrica de distancia y método de agrupación seleccionados
    • La interpretación de componentes principales requiere juicio experto
    • Análisis de correspondencia limitado a variables categóricas disponibles
  3. Contextuales:
    • Cambios en condiciones macroeconómicas pueden alterar patrones
    • Regulaciones y políticas pueden impactar la estructura del mercado
    • Fenómenos exógenos (pandemias, crisis) no contemplados

10.4 Próximos Pasos

  1. Corto plazo (1-3 meses):
    • Validar hallazgos con equipo comercial y expertos de mercado
    • Implementar segmentación en CRM y sistemas de gestión
    • Desarrollar materiales de marketing diferenciados por cluster
  2. Mediano plazo (3-6 meses):
    • Implementar modelos predictivos para pricing y clasificación
    • Crear dashboards interactivos para monitoreo
    • Evaluar desempeño de estrategias diferenciadas por segmento
  3. Largo plazo (6-12 meses):
    • Expandir análisis con datos de transacciones y seguimiento temporal
    • Integrar análisis geoespacial avanzado
    • Desarrollar sistema de recomendación para clientes basado en perfiles

11 Referencias

  1. Jolliffe, I. T., & Cadima, J. (2016). Principal component analysis: a review and recent developments. Philosophical Transactions of the Royal Society A, 374(2065), 20150202.

  2. Kaufman, L., & Rousseeuw, P. J. (2009). Finding groups in data: an introduction to cluster analysis. John Wiley & Sons.

  3. Greenacre, M. (2017). Correspondence analysis in practice. Chapman and Hall/CRC.

  4. Husson, F., Lê, S., & Pagès, J. (2017). Exploratory multivariate analysis by example using R. CRC press.

  5. James, G., Witten, D., Hastie, T., & Tibshirani, R. (2013). An introduction to statistical learning. Springer.

12 Anexos

12.1 Anexo A: Código Completo

El código completo utilizado en este análisis está disponible.

12.2 Anexo B: Descripción de Variables

Tabla detallada con descripción de cada variable del dataset

12.3 Anexo C: Pruebas de Supuestos

Pruebas de normalidad, homogeneidad de varianza, etc. si aplican.

12.4 Anexo D: Análisis de Sensibilidad

Resultados con diferentes números de clusters, componentes, etc.


13 Información de Contacto

Para consultas sobre este análisis:


Fin del informe