1 Contexto

El mercado inmobiliario urbano se caracteriza por su alta complejidad y dinamismo, donde múltiples factores económicos, sociales y geográficos influyen en la oferta y demanda de viviendas. En este contexto, las empresas inmobiliarias enfrentan el reto de tomar decisiones estratégicas basadas en información confiable y en análisis estadísticos que permitan comprender mejor las tendencias del mercado.

La actividad propuesta busca realizar un análisis integral de una base de datos con 8322 registros de propiedades residenciales, recopilados mediante técnicas de webscraping en plataformas digitales de oferta inmobiliaria. Dichos datos incluyen variables cuantitativas como precio, área construida, número de habitaciones, baños y parqueaderos, así como variables cualitativas relacionadas con el tipo de vivienda, zona y barrio.

El objetivo principal es identificar patrones, relaciones y segmentaciones que permitan a la empresa inmobiliaria optimizar sus decisiones de compra, venta y valoración de propiedades. Para ello, se aplicarán técnicas estadísticas avanzadas como el Análisis de Componentes Principales (ACP), el Análisis de Conglomerados y el Análisis de Correspondencia, complementados con recursos de visualización que faciliten la interpretación de los resultados.

Este estudio no solo busca describir el estado actual del mercado, sino también generar recomendaciones estratégicas que otorguen ventajas competitivas en un entorno altamente competitivo y en constante cambio. La combinación de métodos estadísticos y visualización de datos permitirá construir una visión holística del mercado inmobiliario urbano, apoyando la toma de decisiones fundamentadas y orientadas a maximizar beneficios.

2 Exploración incial

2.1 Cargue de la base de datos

# devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
# Cargar librerías necesarias
library(paqueteMODELOS)
library(dplyr)

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

# Crear tabla resumen de variables
tabla_variables <- tibble(
  Variable = names(vivienda),
  Tipo = sapply(vivienda, function(x) class(x)[1]),
  Descripción = c(
    "Identificador único de la propiedad",
    "Zona de la ciudad donde se ubica la vivienda",
    "Número de piso (en caso de apartamentos)",
    "Estrato socioeconómico",
    "Precio de la vivienda (en millones)",
    "Área construida (m²)",
    "Número de parqueaderos",
    "Número de baños",
    "Número de habitaciones",
    "Tipo de vivienda (Casa, Apartamento, etc.)",
    "Barrio donde se ubica la vivienda",
    "Coordenada geográfica (longitud)",
    "Coordenada geográfica (latitud)"
  )
)

# Mostrar tabla
knitr::kable(tabla_variables, caption = "Resumen de variables de la base de datos 'vivienda'")
Resumen de variables de la base de datos ‘vivienda’
Variable Tipo Descripción
id numeric Identificador único de la propiedad
zona character Zona de la ciudad donde se ubica la vivienda
piso character Número de piso (en caso de apartamentos)
estrato numeric Estrato socioeconómico
preciom numeric Precio de la vivienda (en millones)
areaconst numeric Área construida (m²)
parqueaderos numeric Número de parqueaderos
banios numeric Número de baños
habitaciones numeric Número de habitaciones
tipo character Tipo de vivienda (Casa, Apartamento, etc.)
barrio character Barrio donde se ubica la vivienda
longitud numeric Coordenada geográfica (longitud)
latitud numeric Coordenada geográfica (latitud)

2.2 Resumen estadístico de variables numéricas

# Seleccionar solo variables numéricas
vars_num <- vivienda %>%
  select_if(is.numeric)

# Crear tabla resumen con estadísticos básicos
tabla_resumen <- vars_num %>%
  summarise_all(list(
    Min = ~min(., na.rm = TRUE),
    Max = ~max(., na.rm = TRUE),
    Media = ~mean(., na.rm = TRUE),
    Mediana = ~median(., na.rm = TRUE),
    DesvStd = ~sd(., na.rm = TRUE)
  )) %>%
  tidyr::pivot_longer(cols = everything(),
                      names_to = c("Variable", ".value"),
                      names_sep = "_")

# Mostrar tabla en Markdown
knitr::kable(tabla_resumen, caption = "Resumen estadístico de variables numéricas")
Resumen estadístico de variables numéricas
Variable Min Max Media Mediana DesvStd
id 1.00000 8319.0000 4160.000000 4160.000 2401.6327779
estrato 3.00000 6.0000 4.633610 5.000 1.0292221
preciom 58.00000 1999.0000 433.891947 330.000 328.6472443
areaconst 30.00000 1745.0000 174.934938 123.000 142.9641260
parqueaderos 1.00000 10.0000 1.835194 2.000 1.1249088
banios 0.00000 10.0000 3.111311 3.000 1.4282102
habitaciones 0.00000 10.0000 3.605361 3.000 1.4595368
longitud -76.58915 -76.4630 -76.528606 -76.530 0.0173983
latitud 3.33300 3.4977 3.417644 3.416 0.0426385

2.3 Valores faltantes

# Calcular valores faltantes por variable
tabla_na <- vivienda %>%
  summarise_all(~sum(is.na(.))) %>%
  tidyr::pivot_longer(cols = everything(),
                      names_to = "Variable",
                      values_to = "Valores_Faltantes") %>%
  arrange(desc(Valores_Faltantes))

# Mostrar tabla en Markdown
knitr::kable(tabla_na, caption = "Valores faltantes por variable en la base de datos 'vivienda'")
Valores faltantes por variable en la base de datos ‘vivienda’
Variable Valores_Faltantes
piso 2638
parqueaderos 1605
id 3
zona 3
estrato 3
areaconst 3
banios 3
habitaciones 3
tipo 3
barrio 3
longitud 3
latitud 3
preciom 2

2.4 Distribución de Precios

ggplot(vivienda, aes(x = preciom)) +
  geom_histogram(binwidth = 50, fill = "steelblue", color = "white") +
  labs(title = "Distribución de precios de vivienda (millones)",
       x = "Precio (millones)", y = "Frecuencia")

2.5 Relación precio vs área construida

ggplot(vivienda, aes(x = areaconst, y = preciom)) +
  geom_point(alpha = 0.4, color = "darkred") +
  labs(title = "Precio vs Área construida",
       x = "Área construida (m²)", y = "Precio (millones)")

2.6 Boxplot de precios por estrato

ggplot(vivienda, aes(x = factor(estrato), y = preciom)) +
  geom_boxplot(fill = "lightgreen") +
  labs(title = "Distribución de precios por estrato",
       x = "Estrato socioeconómico", y = "Precio (millones)")

2.7 Conteo de tipos de vivienda

# Conteo de tipos de vivienda
tabla_tipos <- vivienda %>%
  group_by(tipo) %>%
  summarise(Conteo = n()) %>%
  arrange(desc(Conteo))

# Mostrar tabla en Markdown
knitr::kable(tabla_tipos, caption = "Conteo de tipos de vivienda en la base de datos 'vivienda'")
Conteo de tipos de vivienda en la base de datos ‘vivienda’
tipo Conteo
Apartamento 5100
Casa 3219
NA 3

2.8 Conteo de viviendas por zona

# Conteo de viviendas por zona
tabla_zonas <- vivienda %>%
  group_by(zona) %>%
  summarise(Conteo = n()) %>%
  arrange(desc(Conteo))

# Mostrar tabla en Markdown
knitr::kable(tabla_zonas, caption = "Conteo de viviendas por zona en la base de datos 'vivienda'")
Conteo de viviendas por zona en la base de datos ‘vivienda’
zona Conteo
Zona Sur 4726
Zona Norte 1920
Zona Oeste 1198
Zona Oriente 351
Zona Centro 124
NA 3

3 Preparación de la base

# 1. Eliminar variables que no aportan al análisis
vivienda_limpia <- vivienda %>%
  select(-id, -longitud, -latitud)

# 2. Eliminar las filas con valores faltantes en 'zona'
vivienda_limpia <- vivienda_limpia %>%
  filter(!is.na(zona))

# 3. Imputar valores faltantes en 'piso' y 'parqueaderos' con la categoría "no_contesta" que es igual a 0
vivienda_limpia <- vivienda_limpia %>%
  mutate(
    piso = ifelse(is.na(piso), "no_contesta", piso),
    parqueaderos = ifelse(is.na(parqueaderos), 0, as.character(parqueaderos))
  )

En el proceso de depuración de la base de datos se realizaron varias transformaciones orientadas a mejorar la calidad de la información y garantizar la pertinencia de las variables para los análisis estadísticos posteriores. En primer lugar, se eliminaron las variables id, longitud y latitud, dado que no aportan información relevante para los objetivos del estudio: el identificador es únicamente un consecutivo sin valor analítico, mientras que las coordenadas geográficas no serán utilizadas en los modelos planteados.

Posteriormente, se identificaron tres registros con valores faltantes en la variable zona. Debido a que estos casos no presentan información en ningún otro campo que permita su recuperación, se decidió eliminarlos de la base, evitando así sesgos en los análisis posteriores.

Finalmente, se abordó el problema de los valores faltantes en las variables piso y parqueaderos, que presentaban una proporción considerable de datos ausentes. Para no perder información y mantener la integridad del conjunto de datos, se optó por una imputación categórica, asignando la etiqueta “no_contesta” a aquellos registros sin respuesta, sin embargo, en el caso de los parqueaderos, el no contesta tiene un valor de 0. Esta estrategia permite conservar los casos en el análisis, diferenciando explícitamente entre datos reportados y datos omitidos, lo cual es metodológicamente más adecuado que la eliminación masiva de registros.

4 Análisis de Componentes Principales

Previo a la aplicación del análisis de componentes principales, se realizaron ajustes en la fase de preparación de datos que dejaron la base sin valores faltantes, garantizando así la consistencia de la información. Sin embargo, durante la exploración inicial se identificó la presencia de valores atípicos en variables como el precio de las viviendas. Estos valores extremos, lejos de ser errores, forman parte de la naturaleza del mercado inmobiliario, donde coexisten propiedades de bajo costo con inmuebles de lujo de alto valor.

Con el fin de evitar que las diferencias de escala entre las variables numéricas generen sesgos en las estimaciones, se procedió a la estandarización de las variables. Este proceso transforma los datos para que cada variable tenga media cero y desviación estándar igual a uno, permitiendo que todas contribuyan de manera equitativa al análisis. De esta forma, se asegura que variables con magnitudes mayores, como el precio o el área construida, no dominen la estructura de los componentes principales.

# One-hot encoding de todas las variables categóricas excepto 'barrio'
#vivienda_dummy <- dummy_cols(
 # vivienda_limpia,
 # select_columns = c("zona", "tipo"),  # variables categóricas a transformar
 # remove_selected_columns = TRUE,              # elimina las originales
 # remove_first_dummy = FALSE                   # conserva todas las categorías
#)

# La variable 'barrio' queda sin transformar
vivienda_limpia$parqueaderos=as.numeric(vivienda_limpia$parqueaderos)
viviendaZ=scale(vivienda_limpia[,3:8])

4.1 Creación de los componentes

prcomp(viviendaZ)
## Standard deviations (1, .., p=6):
## [1] 1.8480703 1.1222455 0.6779600 0.6592367 0.4909833 0.4357909
## 
## Rotation (n x k) = (6 x 6):
##                    PC1        PC2        PC3         PC4         PC5        PC6
## estrato      0.3306904 -0.5816950  0.5551021  0.07749341  0.46143880 -0.1587620
## preciom      0.4781754 -0.1883533 -0.0359721 -0.36062553 -0.21967777  0.7458339
## areaconst    0.4417250  0.2388377 -0.2878930 -0.61783592  0.27859384 -0.4534506
## parqueaderos 0.4096354 -0.2607395 -0.6565763  0.57091588  0.04760414 -0.0700729
## banios       0.4668745  0.1921461  0.3633148  0.18500105 -0.67876421 -0.3437503
## habitaciones 0.2847775  0.6813261  0.2111757  0.34936005  0.44521273  0.2997240

4.2 Elección del número de componentes principales

res.pca <- prcomp(viviendaZ)
fviz_eig(res.pca, addlabels = TRUE)

El gráfico de sedimentación (scree plot) muestra el porcentaje de varianza explicada por cada componente principal. El CP1 explica 56,9% de la variabilidad y el CP2 explica 21,0%, acumulando aproximadamente 77,9% de la varianza total. A partir del CP3 el aporte marginal es reducido (≤ 7,7% cada uno) y la curva se aplana, lo que indica rendimientos decrecientes.

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

El gráfico de variables del Análisis de Componentes Principales muestra cómo las características físicas y económicas de las viviendas se proyectan sobre los dos primeros componentes, que en conjunto explican alrededor del 78% de la variabilidad del conjunto de datos. El primer componente, con un peso dominante del 56,9%, agrupa variables como área construida, número de baños, habitaciones, parqueaderos y precio, las cuales apuntan en la misma dirección y presentan vectores largos. Esto indica que estas variables están fuertemente correlacionadas entre sí y representan un eje relacionado con el tamaño, nivel de equipamiento y valor económico del inmueble.

Por su parte, el segundo componente, que explica el 21% de la variabilidad, captura aspectos adicionales no del todo explicados por el tamaño o el precio. En este eje destacan principalmente las variables habitaciones y estrato, que se proyectan en direcciones opuestas, sugiriendo que aportan información diferenciada sobre la estructura interna del inmueble y el nivel socioeconómico del entorno.

4.3 Conclusión

El Análisis de Componentes Principales permitió identificar que la estructura del mercado inmobiliario urbano analizado está dominada por una dimensión asociada al tamaño, equipamiento y valor económico del inmueble. Esta primera dimensión, que explica el 56,9% de la variabilidad, reúne de manera consistente variables como área, número de baños, habitaciones, parqueaderos y precio, evidenciando que las características físicas y de confort son los elementos más determinantes en la diferenciación de la oferta residencial. Los altos niveles de correlación entre estas variables confirman la existencia de un patrón estructural claro en la valoración de las viviendas.

El segundo componente principal, con un aporte adicional del 21%, introduce una dimensión complementaria relacionada con la configuración interna del inmueble y el nivel socioeconómico del sector. La oposición entre las variables habitaciones y estrato revela matices adicionales que no están completamente explicados por el tamaño o el precio, lo cual es coherente con la segmentación social y urbanística presente en las ciudades latinoamericanas. En conjunto, los dos componentes explican cerca del 78% de la variabilidad total, permitiendo una representación eficiente y altamente interpretable del mercado, y constituyendo una base sólida para los análisis posteriores de segmentación y clasificación.

5 Análisis de Conglomerados

Una vez identificadas las principales dimensiones que explican la variabilidad de las características de las viviendas mediante el Análisis de Componentes Principales, es posible avanzar hacia una etapa de segmentación más profunda. El ACP permitió reducir la complejidad del conjunto de variables originales y sintetizar la información en un espacio de menor dimensión que conserva la mayor parte de la estructura relevante de los datos.

En este contexto, el siguiente paso consiste en aplicar un Análisis de Conglomerados con el fin de identificar grupos homogéneos de viviendas que compartan características comunes. Al utilizar los componentes principales como insumo para el clustering, se garantiza que los grupos resultantes se formen a partir de los patrones estructurales realmente presentes en los datos, evitando que variables altamente correlacionadas distorsionen las distancias entre observaciones.

5.1 Aplicación del análisis de conglomerados

library(paqueteMODELOS)
library(factoextra)
library(ggplot2)
library(dplyr)
library(cluster)
library(tidyverse)

data("vivienda")
# 1. Eliminar variables que no aportan al análisis
vivienda_limpia <- vivienda %>%
  select(-id, -longitud, -latitud)

# 2. Eliminar las filas con valores faltantes en 'zona'
vivienda_limpia <- vivienda_limpia %>%
  filter(!is.na(zona))

# 3. Imputar valores faltantes en 'piso' y 'parqueaderos' con la categoría "no_contesta" que es igual a 0
vivienda_limpia <- vivienda_limpia %>%
  mutate(
    piso = ifelse(is.na(piso), "no_contesta", piso),
    parqueaderos = ifelse(is.na(parqueaderos), 0, as.character(parqueaderos))
  )

vivienda_limpia$parqueaderos=as.numeric(vivienda_limpia$parqueaderos)
viviendaZ=scale(vivienda_limpia[,3:8])
res.pca <- prcomp(viviendaZ)
viviendaZ_df <- as.data.frame(viviendaZ)

# Elegimos cuántos componentes usar para clusterización
ncp <- 2  # puedes cambiar a 3 si lo deseas
scores_pca <- as.data.frame(res.pca$x[, 1:ncp])
colnames(scores_pca) <- paste0("CP", 1:ncp)

# Estandarizamos por si acaso (los scores ya suelen estar en escala comparable, pero es seguro)
scores_pca <- scale(scores_pca) |> as.data.frame()
# ===============================================================
# 1) Distancias
# ===============================================================
# Distancia Euclidiana
dist_eucl <- dist(scores_pca, method = "euclidean")


# ===============================================================
# 2) Clúster jerárquico con diferentes métodos de enlace
# ===============================================================
# Usaremos la distancia Euclidiana sobre el espacio CP
dist_cp <- dist_eucl

# Método "complete"
hc_complete <- hclust(dist_cp, method = "complete")

# Decidir k
k <- 3

# Asignación de clústeres con el método elegido 
cl_asig <- cutree(hc_complete, k = k)


# Data frame con etiquetas
scores_cl <- scores_pca %>%
  mutate(cluster = factor(cl_asig))

# ===============================================================
# 3) Gráfico de puntos (CP1 vs CP2) coloreado por clúster
# ===============================================================
if (ncol(scores_pca) >= 2) {
  ggplot(scores_cl, aes(x = CP1, y = CP2, color = cluster)) +
    geom_point(alpha = .6, size = 2.5) +
    geom_text(aes(label = cluster), vjust = -0.9, size = 3, show.legend = FALSE) +
    theme_classic() +
    labs(title = paste0("Clusters en el espacio de CP (k = ", k, ")"),
         x = "CP1", y = "CP2", color = "Clúster")
}

El Clúster 1 (color rojo) se ubica principalmente hacia valores altos de CP2 y una zona intermedia de CP1. Esta posición indica que contiene viviendas con mayor número de habitaciones, baños o características asociadas a la dimensión representada por CP2, lo que sugiere propiedades más amplias o con mejor equipamiento interno. El Clúster 2 (color verde) se concentra en la región central del plano, con valores moderados de CP1 y CP2. Esto lo convierte en un grupo “intermedio”, compuesto por viviendas con atributos equilibrados en tamaño, área construida y precio. El Clúster 3 (color azul) aparece desplazado hacia valores altos de CP1 y ligeramente bajos de CP2, lo que sugiere viviendas con mayores niveles de tamaño o valor económico, posiblemente asociadas a estratos más altos o propiedades de mayor área.

La separación visual entre los tres grupos evidencia que el método de conglomerados logró identificar segmentos bien diferenciados dentro del mercado inmobiliario. Además, aunque existen zonas de traslape —lo cual es esperado dada la alta heterogeneidad del mercado—, se observan fronteras relativamente claras que indican que los clústeres capturan diferencias reales en las características de las viviendas.

5.2 Dendrogramas y rectángulos de corte

# ===============================================================
# 4) Dendrogramas y rectángulos de corte
# ===============================================================
par(mfrow = c(1,1))
plot(hc_complete, cex=.5, main="Dendrograma - Complete", ylab="Altura", xlab="")
rect.hclust(hc_complete, k = k, border = 2:5)

En la gráfica se observa que las uniones entre observaciones cercanas ocurren en alturas bajas, lo que indica que existe un gran número de viviendas con características muy similares. A medida que asciende la altura del dendrograma, aparecen fusiones cada vez más distantes, lo cual refleja la presencia de grupos más heterogéneos que sólo pueden combinarse a niveles elevados de distancia. La presencia de saltos amplios en las alturas superiores sugiere puntos naturales de corte donde la estructura de los datos cambia drásticamente, facilitando la identificación del número adecuado de conglomerados.

En este caso, el corte dibujado sobre el dendrograma delimita tres grandes clústeres, lo cual es coherente con los saltos visibles en la altura de las fusiones. Los grupos formados presentan tamaños relativamente equilibrados y mantienen una separación horizontal apreciable, lo que indica que las viviendas asignadas a cada conglomerado presentan similitudes internas fuertes y diferencias claras respecto a los otros grupos.

5.3 Calidad de partición: Silhouette

# ===============================================================
# 6) Coeficiente de Silhouette (k elegido)
# ===============================================================
sil <- silhouette(cl_asig, dist_cp)
sil_avg <- mean(sil[, "sil_width"])
cat("Coeficiente de Silhouette promedio para k =", k, ": ", round(sil_avg, 3), "\n")
## Coeficiente de Silhouette promedio para k = 3 :  0.418

El coeficiente de Silhouette promedio obtenido para k=3k=3k=3 fue 0,418, lo que sugiere una estructura de clústeres moderadamente bien definida. La partición en tres grupos ofrece un equilibrio entre separación y compactación interna, con cierta superposición esperable dado el carácter heterogéneo del mercado inmobiliario.

5.4 Conclusión

El ejercicio de segmentación identificó tres clústeres diferenciados y operativamente útiles para describir la oferta inmobiliaria. La elección de k=3 se sustentó en (1) los saltos de altura observados en el dendrograma (puntos naturales de corte), (2) la separación visual en el plano de los dos primeros componentes (grupos con fronteras razonablemente claras) y (3) un coeficiente de Silhouette promedio = 0,418, que indica una estructura de segmentación moderada pero consistente: existen grupos discernibles con cierta superposición en las zonas de frontera, algo esperable en mercados heterogéneos. En términos sustantivos, los clústeres se organizan principalmente alrededor de los ejes ya detectados en el ACP: tamaño/equipamiento–precio y estratificación. De forma general, se reconoce un segmento de mayor valor (inmuebles más grandes y costosos), un segmento intermedio (atributos equilibrados) y un segmento de acceso/asequible (menores áreas, precios y dotaciones), lo que confirma que la oferta se agrupa en submercados coherentes.

6 Análisis de Correspondencia

Para complementar los resultados obtenidos en los análisis previos, se realizará un análisis de correspondencia utilizando únicamente las variables categóricas de la base de datos. Aunque inicialmente se consideró incluir la variable barrio, su alto número de categorías y baja frecuencia en muchas de ellas dificultaba la interpretación y la estabilidad de los resultados. Por esta razón, se decidió trabajar únicamente con la variable zona, la cual agrupa territorialmente a los barrios y permite capturar de manera más sintética la dimensión geográfica del mercado inmobiliario.

Adicionalmente, la variable estrato, que originalmente estaba en formato numérico, fue transformada a una variable categórica para incorporarla en este análisis. De esta forma será posible explorar con mayor precisión cómo se relacionan el tipo de vivienda, la zona y el estrato socioeconómico, ampliando la comprensión cualitativa de la estructura y segmentación del mercado urbano.

6.1 Caracterización de la información

library(paqueteMODELOS)
library(factoextra)
library(dplyr)
library(FactoMineR)
library(tidyr)


data("vivienda")

# Base mínima para AC/MCA (solo las 3 categóricas a analizar)
vivienda_cat <- vivienda %>%
  select(tipo, zona, estrato) %>%     # nos quedamos con las 3 variables
  drop_na(tipo, zona, estrato) %>%    # quitamos NAs en estas columnas
  mutate(
    tipo    = as.factor(tipo),
    zona    = as.factor(zona),
    estrato = as.factor(estrato)      # estrato pasa a categórica
  )

summary(vivienda_cat)
##           tipo                zona      estrato 
##  Apartamento:5100   Zona Centro : 124   3:1453  
##  Casa       :3219   Zona Norte  :1920   4:2129  
##                     Zona Oeste  :1198   5:2750  
##                     Zona Oriente: 351   6:1987  
##                     Zona Sur    :4726

6.2 Tabla con la información cruzada

# Tabla de contingencia 3D (tipo × zona × estrato)
tab3 <- with(vivienda_cat, table(tipo, zona, estrato))

# Tabla “aplanada” (flat table) para lectura en reporte/HTML
ftab3 <- ftable(tab3)

ftab3
##                          estrato    3    4    5    6
## tipo        zona                                    
## Apartamento Zona Centro            14    7    3    0
##             Zona Norte            337  246  498  117
##             Zona Oeste             29   58  231  711
##             Zona Oriente           58    2    1    1
##             Zona Sur              201 1091 1033  462
## Casa        Zona Centro            91    7    1    1
##             Zona Norte            235  161  271   55
##             Zona Oeste             25   26   59   59
##             Zona Oriente          282    6    1    0
##             Zona Sur              181  525  652  581

6.3 Porcentaje de inercia explicada por dimension

# MCA con las 3 variables categóricas
mca_res <- MCA(vivienda_cat, graph = FALSE)

# Inercia por dimensión
mca_res$eig
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1  0.5620882              21.078306                          21.07831
## dim 2  0.4531232              16.992119                          38.07043
## dim 3  0.3796450              14.236687                          52.30711
## dim 4  0.3334444              12.504164                          64.81128
## dim 5  0.3233137              12.124263                          76.93554
## dim 6  0.2717762              10.191608                          87.12715
## dim 7  0.2013563               7.550862                          94.67801
## dim 8  0.1419197               5.321990                         100.00000

6.4 Mapa factorial

fviz_mca_var(mca_res, repel = T, title = "MCA: Tipo, Zona y Estrato")

El mapa factorial revela tres asociaciones territoriales y socioeconómicas principales. En el cuadrante derecho, Zona Oriente y Zona Centro se proyectan juntas y alejadas del origen, en proximidad con Estrato 3, lo que sugiere una co‑ocurrencia por encima de lo esperable bajo independencia. En el cuadrante superior izquierdo, Zona Oeste aparece muy próxima a Estrato 6, indicando un nicho de alto estrato relativamente diferenciado. Por su parte, el cuadrante inferior izquierdo reúne a Zona Sur con Estratos 4 y 5, y en esa misma dirección se ubica Apartamento, lo que sugiere una mayor afinidad relativa de esta tipología con esa zona y esos estratos que con el eje Centro/Oriente.

En cuanto a la tipología Casa y a Zona Norte, ambas se sitúan cerca del origen, por lo que discriminan poco en las dos primeras dimensiones y muestran un comportamiento más “promedio” respecto al conjunto. En términos de ejes, Dimensión 1 (21,1%) contrapone Centro/Oriente–Estrato 3 frente a Sur/Oeste (donde se alinea Apartamento), mientras que Dimensión 2 (17%) separa el bloque Oeste–Estrato 6 (arriba) del bloque Sur–Estratos 4–5 (abajo). Estas configuraciones apuntan a submercados territoriales con perfiles socioeconómicos diferenciados y a una segmentación tipológica más marcada para Apartamento que para Casa en este plano.

6.5 Conclusión

El análisis de correspondencia múltiple entre tipo, zona y estrato evidencia tres focos territoriales y socioeconómicos diferenciados: (i) Zona Oriente–Zona Centro asociados principalmente a estrato 3; (ii) Zona Oeste vinculada al estrato 6 (alto); y (iii) Zona Sur con mayor afinidad por estratos 4–5 y la tipología Apartamento, mientras que Casa y Zona Norte se ubican cerca del origen y, por tanto, discriminan poco en las dos primeras dimensiones.

7 Concluciones y recomendaciones

El análisis integral del mercado inmobiliario permitió identificar patrones estructurales, segmentaciones y asociaciones territoriales que explican de manera consistente la variabilidad y organización de la oferta urbana. El ACP evidenció que las diferencias entre viviendas están dominadas por un eje de tamaño, equipamiento y precio, complementado por una segunda dimensión socioeconómica asociada al estrato. Con base en estas estructuras, el análisis de conglomerados identificó tres segmentos claramente diferenciados: un segmento premium caracterizado por inmuebles amplios y de alto valor; un segmento medio con atributos equilibrados; y un segmento asequible, conformado por propiedades de menor tamaño y precio. Finalmente, el análisis de correspondencia mostró que estas diferencias también se reflejan territorialmente: Zona Oriente–Centro se asocia a estrato 3, Zona Sur a estratos 4 y 5 y al producto Apartamento, mientras que Zona Oeste concentra oferta de estrato 6. Estos hallazgos confirman que la oferta inmobiliaria urbana no es homogénea, sino que se organiza en submercados coherentes tanto en términos físicos como socioeconómicos y territoriales.

A partir de estos resultados, se proponen varias recomendaciones estratégicas para la empresa inmobiliaria. En primer lugar, se sugiere orientar la captación de propiedades premium hacia la Zona Oeste, donde existe una clara concentración de vivienda de estrato alto, lo cual permite maximizar márgenes y fortalecer el portafolio de alto valor. En segundo lugar, el segmento medio, mayoritario y con alta rotación, representa una oportunidad para estrategias de volumen y estabilidad comercial, especialmente en la Zona Sur, donde los apartamentos de estratos 4 y 5 tienen una presencia significativa. En tercer lugar, la oferta asociada al estrato 3 en el corredor Centro–Oriente constituye un mercado sensible al precio, ideal para estrategias de posicionamiento basadas en accesibilidad, financiación flexible y optimización de inventario. De forma transversal, se recomienda integrar estos segmentos en un sistema de pricing diferenciado por zona y tipología, fortalecer los modelos predictivos de valoración con los componentes principales identificados, y utilizar los resultados del clustering y del MCA para diseñar campañas comerciales focalizadas según perfil socioeconómico y localización.