Resumen ejecutivo

Una empresa inmobiliaria necesita entender mejor el mercado urbano de vivienda para tomar decisiones de compra, venta y valoración con más criterio. Para eso se analizaron 8.322 propiedades residenciales (datos obtenidos de OLX, disponibles en el paquete paqueteMODELOS) con tres técnicas de análisis multivariado -componentes principales, conglomerados y correspondencias- apoyadas en mapas y gráficos.

En términos generales, la variación del mercado se puede resumir en dos dimensiones: el tamaño/valor de la propiedad por un lado, y la relación entre estrato y número de habitaciones por otro. A partir de esas dimensiones las propiedades se agrupan en cuatro segmentos con precios, áreas y estratos bastante distintos entre sí, lo que permite pensar en estrategias de precio diferenciadas en lugar de un enfoque único. También se encontró que el tipo de vivienda (casa o apartamento) no se reparte igual en todas las zonas de la ciudad -la relación es estadísticamente significativa- y que tanto los precios como los segmentos siguen un patrón geográfico claro y no aleatorio.

Con esto la empresa puede priorizar zonas, ajustar precios por segmento y enfocar mejor sus esfuerzos comerciales.

1 Introducción y planteamiento del problema

Una empresa inmobiliaria de una gran ciudad quiere entender mejor su mercado de vivienda para tomar decisiones más informadas. Cuenta con una base de datos amplia sobre las propiedades residenciales que tiene en oferta, pero hasta ahora no la ha explotado más allá de lo descriptivo. El objetivo de este trabajo es hacer un análisis más completo de esos datos que ayude a identificar patrones, relaciones y segmentos útiles para las decisiones de compra, venta y valoración de inmuebles.

Para eso se abordan cuatro frentes: primero, un análisis de componentes principales para reducir la dimensionalidad de las variables numéricas y ver qué características explican mejor la variación de precios; segundo, un análisis de conglomerados para agrupar las propiedades en segmentos con características parecidas; tercero, un análisis de correspondencias para ver cómo se relacionan variables categóricas como el tipo de vivienda, la zona y el barrio; y por último, visualizaciones y mapas que resuman todo lo anterior de forma clara para la dirección de la empresa.

2 Marco teórico

Los conceptos usados aquí se apoyan en los tutoriales del paquete paqueteMODELOS (Tutorial101, Tutorial102 y Tutorial103), donde se explican los fundamentos de cada técnica.

El análisis de componentes principales (PCA) es una técnica de reducción de dimensionalidad: toma un grupo de variables numéricas correlacionadas y las transforma en un número menor de componentes ortogonales (no correlacionados entre sí), ordenados de mayor a menor según la varianza que explican. Se calcula a partir de los eigenvalores y eigenvectores de la matriz de correlación, y en la práctica sirve para resumir la información original con la menor pérdida posible de varianza.

El análisis de conglomerados (cluster) es una técnica de aprendizaje no supervisado que agrupa observaciones parecidas entre sí -y distintas de las de otros grupos- a partir de una medida de distancia. Para decidir cuántos grupos usar se suele recurrir al método del codo (que mira cómo cae la varianza intra-clúster a medida que se agregan grupos) o al índice de silueta (que mide qué tan bien separados y cohesionados quedan los grupos).

El análisis de correspondencias explora la relación entre variables categóricas a partir de una tabla de contingencia. Descompone la inercia de esa asociación (el equivalente categórico a la varianza) en dimensiones que se pueden graficar, ubicando las categorías de fila y de columna en un mismo plano. Cuando hay más de dos variables categóricas se usa su extensión, el análisis de correspondencias múltiple (ACM).

3 Descripción y preparación de los datos

3.1 Fuente y variables

data("vivienda")
dim_orig <- dim(vivienda)

La base proviene de un ejercicio de webscraping sobre el portal OLX y contiene 8,322 registros de propiedades residenciales con 13 variables:

data.frame(
  Variable = c("id","zona","piso","estrato","preciom","areaconst","parqueaderos",
               "banios","habitaciones","tipo","barrio","longitud","latitud"),
  Descripción = c("Identificador de la propiedad","Zona geográfica de la ciudad",
                   "Número de piso (alta proporción de datos faltantes)",
                   "Estrato socioeconómico","Precio en millones de pesos",
                   "Área construida (m²)","Número de parqueaderos",
                   "Número de baños","Número de habitaciones",
                   "Tipo de propiedad (Casa / Apartamento)","Barrio",
                   "Coordenada geográfica (longitud)","Coordenada geográfica (latitud)")
) %>% tabla(caption = "Diccionario de variables")
Diccionario de variables
Variable Descripción
id Identificador de la propiedad
zona Zona geográfica de la ciudad
piso Número de piso (alta proporción de datos faltantes)
estrato Estrato socioeconómico
preciom Precio en millones de pesos
areaconst Área construida (m²)
parqueaderos Número de parqueaderos
banios Número de baños
habitaciones Número de habitaciones
tipo Tipo de propiedad (Casa / Apartamento)
barrio Barrio
longitud Coordenada geográfica (longitud)
latitud Coordenada geográfica (latitud)

Las coordenadas y los nombres de barrio (Valle del Lili, Ciudad Jardín, Pance, La Flora, entre otros) dejan ver que se trata de Santiago de Cali, lo cual ayuda a interpretar mejor los resultados geográficos más adelante.

3.2 Calidad de los datos y tratamiento

na_tab <- data.frame(Variable = names(vivienda), Faltantes = colSums(is.na(vivienda))) %>%
  mutate(`% Faltante` = round(100*Faltantes/nrow(vivienda),1)) %>%
  arrange(desc(Faltantes))
na_tab %>% tabla(caption = "Valores faltantes por variable", digits = 1)
Valores faltantes por variable
Variable Faltantes % Faltante
piso piso 2,638 31.7
parqueaderos parqueaderos 1,605 19.3
id id 3 0.0
zona zona 3 0.0
estrato estrato 3 0.0
areaconst areaconst 3 0.0
banios banios 3 0.0
habitaciones habitaciones 3 0.0
tipo tipo 3 0.0
barrio barrio 3 0.0
longitud longitud 3 0.0
latitud latitud 3 0.0
preciom preciom 2 0.0

piso (32% de faltantes) y parqueaderos (19%) son las variables con más datos ausentes; las demás tienen faltantes marginales, de máximo 3 registros. Por eso piso se deja por fuera de los análisis cuantitativos: no aporta lo suficiente como para justificar el hueco de información que tiene. Para PCA y conglomerados se usan solo los registros completos en las variables numéricas relevantes (incluyendo parqueaderos), y para correspondencias se usan los registros completos en zona, tipo, barrio y estrato, que al no depender de parqueaderos permite conservar más observaciones. Además, preciom y areaconst se transforman con logaritmo natural antes de PCA y cluster, porque tienen un sesgo marcado hacia la derecha (la media casi dobla la mediana) y sin esa transformación unas pocas propiedades de lujo terminarían dominando el análisis.

num_vars <- c("estrato","preciom","areaconst","parqueaderos","banios","habitaciones")

viv_num <- vivienda %>%
  filter(if_all(all_of(c(num_vars, "zona","tipo","latitud","longitud")), ~ !is.na(.))) %>%
  mutate(log_preciom = log(preciom), log_areaconst = log(areaconst))

n_pca <- nrow(viv_num)

El conjunto depurado para PCA y cluster conserva 6,717 propiedades, un 80.7% del total.

3.3 Estadística descriptiva

vivienda %>%
  select(estrato, preciom, areaconst, parqueaderos, banios, habitaciones) %>%
  summary() %>% as.data.frame.matrix() %>% tabla(caption = "Resumen estadístico de variables numéricas")
Resumen estadístico de variables numéricas
estrato preciom areaconst parqueaderos banios habitaciones
X Min. :3.000 Min. : 58.0 Min. : 30.0 Min. : 1.000 Min. : 0.000 Min. : 0.000
X.1 1st Qu.:4.000 1st Qu.: 220.0 1st Qu.: 80.0 1st Qu.: 1.000 1st Qu.: 2.000 1st Qu.: 3.000
X.2 Median :5.000 Median : 330.0 Median : 123.0 Median : 2.000 Median : 3.000 Median : 3.000
X.3 Mean :4.634 Mean : 433.9 Mean : 174.9 Mean : 1.835 Mean : 3.111 Mean : 3.605
X.4 3rd Qu.:5.000 3rd Qu.: 540.0 3rd Qu.: 229.0 3rd Qu.: 2.000 3rd Qu.: 4.000 3rd Qu.: 4.000
X.5 Max. :6.000 Max. :1999.0 Max. :1745.0 Max. :10.000 Max. :10.000 Max. :10.000
X.6 NA’s :3 NA’s :2 NA’s :3 NA’s :1605 NA’s :3 NA’s :3
ggplot(vivienda %>% filter(!is.na(zona)), aes(x = reorder(zona, preciom, median), y = preciom, fill = zona)) +
  geom_boxplot(show.legend = FALSE, outlier.alpha = 0.3) +
  scale_fill_manual(values = colorRampPalette(paleta_seg)(5)) +
  coord_flip() +
  labs(x = NULL, y = "Precio (millones COP)") +
  theme_minimal(base_size = 12)
Distribución de precio por zona

Distribución de precio por zona

mat_cor <- cor(viv_num %>% select(estrato, log_preciom, log_areaconst, parqueaderos, banios, habitaciones))
corrplot(mat_cor, method = "color", type = "upper", addCoef.col = "black",
         tl.col = "black", tl.srt = 45, number.cex = 0.8, col = colorRampPalette(c(col_sec,"white",col_prin))(200))
Matriz de correlación entre variables numéricas

Matriz de correlación entre variables numéricas

Las variables numéricas están correlacionadas entre sí de forma moderada a fuerte (precio-área y área-baños, por ejemplo), lo cual justifica reducir su dimensionalidad con PCA.

4 Metodología

El flujo de trabajo fue el siguiente. Primero se depuraron los datos: se trataron los faltantes, se transformaron con logaritmo las variables más asimétricas y se estandarizaron (media 0, varianza 1) antes de entrar a PCA y cluster. Luego se corrió el PCA con FactoMineR::PCA() sobre las seis variables numéricas estandarizadas, seleccionando el número de componentes con el criterio del codo y la varianza acumulada. Para el cluster, el número de grupos se definió con el índice de silueta (factoextra::fviz_nbclust) calculado sobre una muestra representativa, y el modelo final se ajustó con k-means (nstart = 25) sobre todo el conjunto depurado; los grupos resultantes se renombraron como segmentos de mercado según su precio promedio, para que sean más fáciles de leer desde el negocio. Para las correspondencias se construyó una tabla de contingencia zona-tipo (correspondencia clásica, con prueba chi-cuadrado de independencia) y un análisis de correspondencias múltiple entre zona, tipo y barrio, agrupando los barrios menos frecuentes en la categoría “Otros” para no perder interpretabilidad. Por último, se generaron mapas de dispersión geográfica coloreados por precio y por segmento.

Todo el análisis se hizo en R, con los paquetes FactoMineR, factoextra, ggplot2 y dplyr.

5 Resultados

5.1 Análisis de Componentes Principales

pca_vars <- viv_num %>% select(estrato, log_preciom, log_areaconst, parqueaderos, banios, habitaciones)
res.pca <- PCA(pca_vars, scale.unit = TRUE, graph = FALSE)
eig_tab <- as.data.frame(res.pca$eig)
names(eig_tab) <- c("Eigenvalor","% Varianza","% Varianza acumulada")
fviz_eig(res.pca, addlabels = TRUE, barfill = col_prin, barcolor = col_prin, linecolor = col_sec) +
  labs(title = NULL, x = "Componente", y = "% de varianza explicada")
Varianza explicada por componente

Varianza explicada por componente

eig_tab %>% tabla(caption = "Varianza explicada por componente principal", digits = 2)
Varianza explicada por componente principal
Eigenvalor % Varianza % Varianza acumulada
comp 1 3.67 61.23 61.23
comp 2 1.21 20.24 81.47
comp 3 0.49 8.10 89.57
comp 4 0.29 4.78 94.35
comp 5 0.24 3.94 98.29

Las dos primeras componentes explican 81.5% de la varianza total, suficiente para resumir la estructura del mercado en un plano de dos dimensiones sin perder demasiada información.

fviz_pca_var(res.pca, col.var = "contrib", gradient.cols = c(col_terc, col_sec, "#7a0177"),
             repel = TRUE) + labs(title = NULL)
Círculo de correlación de variables

Círculo de correlación de variables

data.frame(Variable = rownames(res.pca$var$cor),
           `Correlación Dim.1` = round(res.pca$var$cor[,1],2),
           `Correlación Dim.2` = round(res.pca$var$cor[,2],2),
           `Contribución Dim.1 (%)` = round(res.pca$var$contrib[,1],1),
           `Contribución Dim.2 (%)` = round(res.pca$var$contrib[,2],1),
           check.names = FALSE) %>%
  tabla(caption = "Correlación y contribución de variables a los dos primeros componentes")
Correlación y contribución de variables a los dos primeros componentes
Variable Correlación Dim.1 Correlación Dim.2 Contribución Dim.1 (%) Contribución Dim.2 (%)
estrato estrato 0.6 -0.7 9.2 41.7
log_preciom log_preciom 0.9 -0.2 22.8 5.2
log_areaconst log_areaconst 0.9 0.2 21.9 3.1
parqueaderos parqueaderos 0.8 -0.1 16.3 1.9
banios banios 0.9 0.2 21.0 2.9
habitaciones habitaciones 0.6 0.7 8.8 45.3

La primera dimensión se puede leer como “tamaño y valor de la propiedad”: correlaciona positivamente con precio, área, baños y parqueaderos, y separa las propiedades grandes y costosas (a la derecha) de las pequeñas y económicas (a la izquierda). La segunda dimensión contrasta el estrato (negativo) con el número de habitaciones (positivo), y en la práctica separa viviendas de estrato alto con pocas habitaciones -típicamente apartamentos- de viviendas de estrato más bajo pero con más habitaciones, como suelen ser las casas familiares grandes.

fviz_pca_ind(res.pca, geom = "point", alpha.ind = 0.4,
             col.ind = viv_num$tipo, palette = c(col_prin, col_sec),
             addEllipses = TRUE, legend.title = "Tipo") + labs(title = NULL)
Individuos proyectados en el plano principal, coloreados por tipo de vivienda

Individuos proyectados en el plano principal, coloreados por tipo de vivienda

Casas y apartamentos ocupan zonas parcialmente distintas del plano, sobre todo a lo largo de la segunda dimensión, lo cual tiene sentido dadas sus diferencias típicas en número de habitaciones y estrato.

5.2 Análisis de Conglomerados

set.seed(123)
muestra_idx <- sample(seq_len(nrow(pca_vars)), min(1500, nrow(pca_vars)))
fviz_nbclust(scale(pca_vars[muestra_idx, ]), kmeans, method = "silhouette", k.max = 8) +
  labs(title = NULL)
Selección del número óptimo de clústeres (índice de silueta, muestra representativa)

Selección del número óptimo de clústeres (índice de silueta, muestra representativa)

set.seed(123)
k_final <- 4
km <- kmeans(scale(pca_vars), centers = k_final, nstart = 25)
viv_num$cluster_raw <- factor(km$cluster)

perfil <- viv_num %>% group_by(cluster_raw) %>%
  summarise(n = n(), precio = mean(preciom), area = mean(areaconst),
            estrato = mean(estrato), parqueaderos = mean(parqueaderos),
            banios = mean(banios), habitaciones = mean(habitaciones)) %>%
  arrange(desc(precio))

nombres_segmento <- c("Premium", "Amplio de gama media", "Estándar", "Económico compacto")[1:k_final]
mapa_nombres <- setNames(nombres_segmento, perfil$cluster_raw)
viv_num$segmento <- factor(mapa_nombres[as.character(viv_num$cluster_raw)], levels = nombres_segmento)
perfil$segmento <- nombres_segmento

sil_idx <- sample(seq_len(nrow(pca_vars)), min(2000, nrow(pca_vars)))
sil <- silhouette(km$cluster[sil_idx], dist(scale(pca_vars)[sil_idx, ]))
sil_avg <- round(mean(sil[,3]), 2)

Con el índice de silueta se llegó a 4 conglomerados, ajustados con k-means sobre las 6,717 propiedades del conjunto depurado. El índice de silueta promedio, estimado sobre una muestra de validación, quedó en 0.3.

Para que sean más fáciles de usar comercialmente, los clústeres se renombraron como segmentos de mercado según su precio promedio:

perfil %>% select(Segmento = segmento, `N° propiedades` = n, `Precio prom. (M COP)` = precio,
                    `Área prom. (m²)` = area, `Estrato prom.` = estrato,
                    `Parqueaderos prom.` = parqueaderos, `Baños prom.` = banios,
                    `Habitaciones prom.` = habitaciones) %>%
  tabla(caption = "Perfil promedio de cada segmento de mercado", digits = 2)
Perfil promedio de cada segmento de mercado
Segmento N° propiedades Precio prom. (M COP) Área prom. (m²) Estrato prom. Parqueaderos prom. Baños prom. Habitaciones prom.
Premium 986 1,066.56 391.91 5.71 3.76 5.15 4.40
Amplio de gama media 2,124 511.30 164.43 5.49 1.92 3.42 3.29
Estándar 853 439.93 283.61 4.03 1.70 4.20 5.84
Económico compacto 2,754 231.15 86.82 4.25 1.12 2.16 2.89
fviz_cluster(list(data = scale(pca_vars), cluster = viv_num$segmento),
             geom = "point", alpha = 0.4, palette = paleta_seg,
             ellipse.type = "convex", ggtheme = theme_minimal(base_size = 12),
             legend.title = "Segmento") + labs(title = NULL)
Segmentos de mercado proyectados sobre las dos primeras componentes principales

Segmentos de mercado proyectados sobre las dos primeras componentes principales

tab_seg_tipo <- table(viv_num$segmento, viv_num$tipo)
tab_seg_zona <- table(viv_num$segmento, viv_num$zona)
ggplot(viv_num, aes(x = segmento, y = preciom, fill = segmento)) +
  geom_boxplot(show.legend = FALSE, outlier.alpha = 0.3) +
  scale_fill_manual(values = paleta_seg) +
  labs(x = NULL, y = "Precio (millones COP)") +
  theme_minimal(base_size = 12) +
  theme(axis.text.x = element_text(angle = 15, hjust = 1))
Distribución de precio por segmento

Distribución de precio por segmento

En resumen, el segmento Premium agrupa las propiedades de mayor precio y área -pensando en valorización y clientes de alto poder adquisitivo-, mientras que Económico compacto concentra la oferta más económica y compacta, más relevante para estrategias de volumen y rotación rápida.

5.3 Análisis de Correspondencias

5.3.1 Zona × tipo de vivienda

viv_cat <- vivienda %>% filter(!is.na(zona), !is.na(tipo), !is.na(barrio), !is.na(estrato))
tab_zt <- table(viv_cat$zona, viv_cat$tipo)
chi_zt <- chisq.test(tab_zt)
as.data.frame.matrix(tab_zt) %>% tabla(caption = "Tabla de contingencia: Zona × Tipo de vivienda")
Tabla de contingencia: Zona × Tipo de vivienda
Apartamento Casa
Zona Centro 24 100
Zona Norte 1,198 722
Zona Oeste 1,029 169
Zona Oriente 62 289
Zona Sur 2,787 1,939

La prueba chi-cuadrado de independencia (X² = 690.9, gl = 4, p < 0.001) confirma que zona y tipo de vivienda están asociados de forma significativa: la oferta de apartamentos y casas no se reparte igual en toda la ciudad.

Como tipo solo tiene dos categorías, esa asociación queda resumida en una única dimensión (el rango es mín(filas-1, columnas-1) = 1), así que en vez de un mapa de correspondencia en dos dimensiones se muestra directamente como proporciones por zona:

ggplot(viv_cat, aes(x = reorder(zona, as.numeric(factor(tipo))), fill = tipo)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = c(col_prin, col_sec), name = "Tipo") +
  scale_y_continuous(labels = scales::percent) +
  coord_flip() +
  labs(x = NULL, y = "Proporción") +
  theme_minimal(base_size = 12)
Proporción de tipo de vivienda por zona (componente de correspondencia)

Proporción de tipo de vivienda por zona (componente de correspondencia)

Zona Oeste tiene una proporción mayor de apartamentos, mientras que en Zona Oriente y Zona Centro predominan las casas. Zona Norte y Zona Sur, que concentran el mayor volumen de oferta, tienen una mezcla más pareja de los dos tipos.

5.3.2 Zona, tipo y barrio (correspondencias múltiples)

top_barrios <- names(sort(table(viv_cat$barrio), decreasing = TRUE))[1:10]
viv_cat <- viv_cat %>% mutate(barrio_grp = ifelse(barrio %in% top_barrios, barrio, "Otros"))
mca_data <- viv_cat %>% select(zona, tipo, barrio_grp) %>% mutate(across(everything(), as.factor))
res.mca <- MCA(mca_data, graph = FALSE)
eig_mca <- as.data.frame(res.mca$eig)[1:5, ]
names(eig_mca) <- c("Eigenvalor","% Inercia","% Inercia acumulada")

Para ver zona, tipo y barrio al mismo tiempo se aplicó un análisis de correspondencias múltiple, agrupando los barrios menos frecuentes en la categoría “Otros” (se dejaron los 10 barrios más frecuentes de forma individual).

eig_mca %>% tabla(caption = "Inercia explicada por dimensión (ACM)", digits = 2)
Inercia explicada por dimensión (ACM)
Eigenvalor % Inercia % Inercia acumulada
dim 1 0.56 11.25 11.25
dim 2 0.53 10.63 21.89
dim 3 0.45 9.01 30.90
dim 4 0.35 7.06 37.96
dim 5 0.33 6.67 44.63
fviz_mca_var(res.mca, repel = TRUE, col.var = "contrib",
             gradient.cols = c(col_terc, col_sec, "#7a0177")) + labs(title = NULL)
Mapa de categorías: zona, tipo y barrio (ACM)

Mapa de categorías: zona, tipo y barrio (ACM)

El primer eje separa sobre todo a Zona Oeste (con barrios como Ciudad Jardín y Pance) del resto de la ciudad, y el segundo diferencia a Zona Norte de barrios con alta concentración de oferta como La Flora y Valle del Lili. En la práctica, barrio y zona terminan contando una historia parecida, pero el barrio agrega un nivel de detalle que la zona por sí sola no captura.

5.4 Visualización geográfica y de mercado

ggplot(viv_num, aes(x = longitud, y = latitud, color = log_preciom)) +
  geom_point(alpha = 0.5, size = 1) +
  scale_color_gradient(low = col_terc, high = "#7a0177", name = "log(Precio)") +
  coord_fixed(1.05) +
  labs(x = "Longitud", y = "Latitud") +
  theme_minimal(base_size = 12)
Distribución geográfica de precios

Distribución geográfica de precios

ggplot(viv_num, aes(x = longitud, y = latitud, color = segmento)) +
  geom_point(alpha = 0.5, size = 1) +
  scale_color_manual(values = paleta_seg, name = "Segmento") +
  coord_fixed(1.05) +
  labs(x = "Longitud", y = "Latitud") +
  theme_minimal(base_size = 12)
Distribución geográfica de los segmentos de mercado

Distribución geográfica de los segmentos de mercado

Los mapas dejan ver que el precio y el segmento no se distribuyen al azar en el espacio: hay agrupaciones geográficas claras -el segmento Premium, por ejemplo, se concentra en corredores específicos de la ciudad- que van en la misma línea de lo que ya mostraba el análisis de correspondencias.

6 Conclusiones

La variabilidad del mercado analizado se explica, en buena parte, por dos dimensiones: el tamaño/valor de la propiedad y la relación entre estrato y número de habitaciones. Sobre esa base, el mercado se divide en 4 segmentos con perfiles bastante distintos en precio, área y estrato, que van desde el Premium de alto valor hasta el Económico compacto de alta rotación. También queda claro que la zona y el tipo de vivienda están asociados de forma significativa, y que el barrio agrega un nivel de detalle adicional dentro de cada zona. Por último, tanto el precio como los segmentos siguen un patrón espacial bastante marcado, visible en los mapas y coherente con el análisis de correspondencias, lo que confirma que la ubicación pesa mucho en el valor de una propiedad.

7 Recomendaciones estratégicas

Con estos resultados, tiene sentido que la empresa maneje precios diferenciados por segmento en lugar de un precio único por zona, usando los perfiles descritos arriba como referencia. También conviene priorizar geográficamente: concentrar la captación de propiedades Premium en las zonas y barrios donde ya se agrupan, y usar el segmento Económico compacto para estrategias de volumen. Como Zona Oeste concentra apartamentos y Zona Oriente/Centro concentran casas, vale la pena ajustar el portafolio de captación según lo que realmente se mueve en cada zona. Y en general, conviene repetir este tipo de análisis cada cierto tiempo a medida que se actualice la base de datos, para detectar cambios en el mercado a tiempo.

8 Anexos

8.1 Anexo A. Tablas complementarias

as.data.frame.matrix(tab_seg_tipo) %>% tabla(caption = "Segmento × Tipo de vivienda")
Segmento × Tipo de vivienda
Apartamento Casa
Premium 296 690
Amplio de gama media 1,550 574
Estándar 40 813
Económico compacto 2,345 409
as.data.frame.matrix(tab_seg_zona) %>% tabla(caption = "Segmento × Zona")
Segmento × Zona
Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
Premium 2 104 263 1 616
Amplio de gama media 2 361 653 0 1,108
Estándar 38 181 47 93 494
Económico compacto 22 641 135 69 1,887
data.frame(Categoría = rownames(res.mca$var$contrib),
           `Contribución Dim.1 (%)` = round(res.mca$var$contrib[,1],1),
           `Contribución Dim.2 (%)` = round(res.mca$var$contrib[,2],1),
           check.names = FALSE) %>%
  arrange(desc(`Contribución Dim.1 (%)`)) %>%
  tabla(caption = "Contribución de categorías a las dimensiones del ACM")
Contribución de categorías a las dimensiones del ACM
Categoría Contribución Dim.1 (%) Contribución Dim.2 (%)
Zona Oeste Zona Oeste 33.0 4.3
santa teresita santa teresita 19.0 4.1
los cristales los cristales 11.3 2.3
Zona Sur Zona Sur 11.2 9.4
Casa Casa 6.5 2.7
ciudad jardín ciudad jardín 4.2 1.8
Apartamento Apartamento 4.1 1.7
pance pance 2.8 1.8
valle del lili valle del lili 2.2 8.4
Zona Norte Zona Norte 1.2 30.9
el caney el caney 1.1 1.1
el ingenio el ingenio 0.9 1.2
la flora la flora 0.9 15.1
la hacienda la hacienda 0.7 1.0
Zona Oriente Zona Oriente 0.5 2.3
Zona Centro Zona Centro 0.2 0.8
Otros Otros 0.2 3.8
acopi acopi 0.1 7.4

8.2 Anexo B. Código fuente y reproducibilidad

El código de cada sección se puede ver desplegando los bloques (“Code”) en la versión HTML del informe. Todo el documento se generó de forma reproducible con R Markdown, directamente sobre los datos de paqueteMODELOS.

sessionInfo()[1:3]
## $R.version
## $R.version$platform
## [1] "x86_64-w64-mingw32"
## 
## $R.version$arch
## [1] "x86_64"
## 
## $R.version$os
## [1] "mingw32"
## 
## $R.version$crt
## [1] "ucrt"
## 
## $R.version$system
## [1] "x86_64, mingw32"
## 
## $R.version$status
## [1] ""
## 
## $R.version$major
## [1] "4"
## 
## $R.version$minor
## [1] "5.2"
## 
## $R.version$year
## [1] "2025"
## 
## $R.version$month
## [1] "10"
## 
## $R.version$day
## [1] "31"
## 
## $R.version$`svn rev`
## [1] "88974"
## 
## $R.version$language
## [1] "R"
## 
## $R.version$version.string
## [1] "R version 4.5.2 (2025-10-31 ucrt)"
## 
## $R.version$nickname
## [1] "[Not] Part in a Rumble"
## 
## 
## $platform
## [1] "x86_64-w64-mingw32/x64"
## 
## $locale
## [1] "LC_COLLATE=Spanish_Colombia.utf8;LC_CTYPE=Spanish_Colombia.utf8;LC_MONETARY=Spanish_Colombia.utf8;LC_NUMERIC=C;LC_TIME=Spanish_Colombia.utf8"

8.3 Anexo C. Referencias

  • Centro MAGIS (Pontificia Universidad Javeriana Cali). paqueteMODELOS: Tutorial101 (Análisis de Componentes Principales), Tutorial102 (Análisis de Conglomerados), Tutorial103 (Análisis de Correspondencia). https://github.com/centro-magis/paqueteMODELOS
  • Jolliffe, I. T. (2002). Principal Component Analysis (2nd ed.). Springer.
  • Hair, J. F., Black, W. C., Babin, B. J., & Anderson, R. E. (2019). Multivariate Data Analysis (8th ed.). Cengage.
  • Greenacre, M. (2017). Correspondence Analysis in Practice (3rd ed.). CRC Press.
  • Kassambara, A. (2017). Practical Guide to Principal Component Methods in R. STHDA.

Modelos Estadísticos para la Toma de Decisiones — Pontificia Universidad Javeriana, Grupo B
Johan David Perdomo Campos