# Función para dar formato uniforme a las tablas
formato_tabla <- function(tabla, caption, digits = 2) {
tabla %>%
kable(
caption = caption,
digits = digits,
align = "c",
booktabs = TRUE
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
position = "center",
font_size = 11
) %>%
row_spec(0, bold = TRUE) %>%
column_spec(1, bold = TRUE)
}El mercado inmobiliario residencial presenta diferencias importantes entre las propiedades no solo por su precio, sino también por variables como el área construida, el número de habitaciones y baños, la disponibilidad de parqueaderos, el estrato y la localización. Un análisis aislado de cada variable puede ocultar patrones que aparecen cuando las características se estudian de manera conjunta.
En este trabajo se analiza una base de viviendas de Cali mediante técnicas de análisis multivariado. El propósito es identificar estructuras comunes en las propiedades, segmentar la oferta residencial y estudiar la asociación entre sus principales características categóricas. Los resultados se orientan a una lectura empresarial del mercado, de manera que puedan utilizarse como apoyo para decisiones de comercialización, segmentación e inversión.
El análisis se desarrolla en cuatro etapas: preparación y exploración de la información, análisis de componentes principales, análisis de conglomerados y análisis de correspondencias. Finalmente, los resultados se integran mediante visualizaciones y recomendaciones para la toma de decisiones.
Caracterizar la oferta residencial de Cali mediante técnicas de análisis multivariado que permitan reducir la dimensionalidad, identificar segmentos homogéneos y estudiar las asociaciones entre las principales características categóricas de las viviendas.
La base vivienda contiene información de viviendas
residenciales de Cali. Primero se revisan sus dimensiones, nombres de
variables y estructura general.
## Número de observaciones: 8322
## Número de variables: 13
## 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")=<pointer: (nil)>
Se revisa la presencia de valores faltantes y duplicados. La variable
id se utiliza únicamente como identificador y, por tanto,
no debe participar en las técnicas multivariadas.
na_resumen <- data.frame(
variable = names(vivienda),
faltantes = sapply(vivienda, function(x) sum(is.na(x))),
porcentaje = round(sapply(vivienda, function(x) mean(is.na(x)) * 100), 2)
)
colnames(na_resumen) <- c(
"Variable",
"Valores faltantes",
"Porcentaje de faltantes"
)
formato_tabla(
na_resumen,
"Valores faltantes por variable",
digits = 2
)| Variable | Valores faltantes | Porcentaje de faltantes | |
|---|---|---|---|
| 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 |
## Duplicados en id: 2
Se eliminan los registros sin identificador y los identificadores duplicados, conservando una sola observación por vivienda.
vivienda <- vivienda %>%
filter(!is.na(id)) %>%
distinct(id, .keep_all = TRUE)
cat("Duplicados en id:", sum(duplicated(vivienda$id)), "\n")## Duplicados en id: 0
Se ientifica que variables poseen faltantes:
## id zona piso estrato preciom areaconst
## 0 0 2635 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 1602 0 0 0 0 0
## latitud
## 0
El número de piso es una variable discreta. Para conservar la
información disponible y evitar una imputación basada únicamente en un
promedio, se utiliza mice con imputación múltiple mediante
predictive mean matching (PMM), tomando como variables auxiliares
características físicas y de localización de las viviendas.
vivienda <- vivienda %>%
mutate(piso = as.numeric(piso))
# Distribución de piso antes de la imputación
ggplot(vivienda, aes(x = piso)) +
geom_bar(fill = "#4E79A7", width = 0.7) +
geom_text(
stat = "count",
aes(label = after_stat(count)),
vjust = -0.4,
size = 3.5
) +
labs(
title = "Distribución del número de piso",
subtitle = "Antes del proceso de imputación",
x = "Piso",
y = "Número de viviendas"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 16),
plot.subtitle = element_text(size = 11),
axis.title = element_text(face = "bold"),
panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank()
)# Variables auxiliares para imputar piso
imp_piso <- vivienda %>%
select(estrato, preciom, areaconst, parqueaderos, banios,
habitaciones, zona, tipo, piso)
# PMM: la variable piso toma valores de viviendas observadas similares
imp <- mice(imp_piso, m = 5, maxit = 30, method = "pmm", seed = 123, printFlag = FALSE)
imp_completo <- complete(imp, 1)
vivienda$piso <- imp_completo$piso
ggplot(vivienda, aes(x = piso)) +
geom_bar(fill = "#4E79A7", width = 0.7) +
geom_text(
stat = "count",
aes(label = after_stat(count)),
vjust = -0.4,
size = 3.5
) +
labs(
title = "Distribución del número de piso",
subtitle = "Después del proceso de imputación",
x = "Piso",
y = "Número de viviendas"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 16),
plot.subtitle = element_text(size = 11),
axis.title = element_text(face = "bold"),
panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank()
)
No se evidencias cambios en la distribucion de las frecuencias posterior
al proceso de imputaicon en la vriable piso.
Durante la revisión de la variable parqueaderos se identificaron valores faltantes en una variable que registra el número de parqueaderos disponibles en cada vivienda. En los registros observados se presentan valores enteros correspondientes a la cantidad de parqueaderos, mientras que los valores faltantes no permiten establecer directamente si se trata de una ausencia de parqueadero o de información no registrada.
Para efectos del análisis y con el propósito de conservar las observaciones disponibles, se adopta como supuesto operativo que los valores faltantes representan la ausencia de parqueaderos y, por tanto, se recodifican como cero. Esta decisión debe interpretarse como un criterio de tratamiento de datos y no como una confirmación de que todas las viviendas con información faltante carezcan efectivamente de parqueadero.
vivienda <- vivienda %>%
mutate(
parqueaderos = as.numeric(parqueaderos),
parqueaderos = ifelse(is.na(parqueaderos), 0, parqueaderos)
)
sapply(vivienda[c("piso", "parqueaderos")], function(x) sum(is.na(x)))## piso parqueaderos
## 0 0
variables_numericas <- c(
"piso",
"estrato",
"areaconst",
"parqueaderos",
"preciom",
"banios",
"habitaciones"
)
# Estadísticos descriptivos
describe_resultado <- psych::describe(
vivienda[, variables_numericas]
)
# Seleccionar estadísticos relevantes
tabla_descriptiva <- describe_resultado[, c(
"n",
"mean",
"sd",
"min",
"max"
)]
# Nombres de las columnas
colnames(tabla_descriptiva) <- c(
"Observaciones",
"Media",
"Desviación estándar",
"Mínimo",
"Máximo"
)
# Nombres descriptivos de las variables
rownames(tabla_descriptiva) <- c(
"Piso",
"Estrato",
"Área construida (m²)",
"Parqueaderos",
"Precio (millones)",
"Baños",
"Habitaciones"
)
# Tabla final
formato_tabla(
tabla_descriptiva,
"Resumen descriptivo de las variables cuantitativas",
digits = 2
)| Observaciones | Media | Desviación estándar | Mínimo | Máximo | |
|---|---|---|---|---|---|
| Piso | 8319 | 3.71 | 2.59 | 1 | 12 |
| Estrato | 8319 | 4.63 | 1.03 | 3 | 6 |
| Área construida (m²) | 8319 | 174.93 | 142.96 | 30 | 1745 |
| Parqueaderos | 8319 | 1.48 | 1.24 | 0 | 10 |
| Precio (millones) | 8319 | 433.90 | 328.67 | 58 | 1999 |
| Baños | 8319 | 3.11 | 1.43 | 0 | 10 |
| Habitaciones | 8319 | 3.61 | 1.46 | 0 | 10 |
La revisión inicial permite comprobar la escala de las variables y detectar diferencias importantes entre magnitudes. Por esta razón, para las técnicas que dependen de distancias y varianzas se utilizarán variables estandarizadas.
Antes de aplicar PCA se estudian las asociaciones lineales entre las variables cuantitativas seleccionadas.
base__viv <- vivienda %>%
select(
piso,
estrato,
areaconst,
parqueaderos,
preciom,
banios,
habitaciones
) %>%
mutate(across(everything(), as.numeric))
cor_matrix <- cor(
base__viv,
use = "pairwise.complete.obs"
)
corrplot(cor_matrix,
method = "color",
type = "upper",
tl.col = "black",
tl.srt = 45,
addCoef.col = "black",
number.cex = 0.65,
title = "Correlaciones entre características de las viviendas",
mar = c(0, 0, 2, 0))La matriz permite identificar qué características tienden a moverse conjuntamente. Estas relaciones sirven como punto de partida para comprender por qué una reducción de dimensionalidad puede ser útil en este conjunto de datos.
El PCA permite representar un conjunto de variables cuantitativas mediante nuevas dimensiones que concentran la mayor parte de la variabilidad observada. Para evitar que las variables con mayor escala dominen el resultado, se trabaja con variables estandarizadas.
pca_data <- vivienda %>%
select(piso, estrato, areaconst, parqueaderos,
preciom, banios, habitaciones) %>%
drop_na()
pca_scale <- scale(pca_data)
res_pca <- prcomp(pca_scale, center = TRUE, scale. = TRUE)
fviz_eig(res_pca, addlabels = TRUE, ylim = c(0, 80)) +
labs(title = "Varianza explicada por los componentes principales",
x = "Componente",
y = "Porcentaje de varianza explicada")var_exp <- summary(res_pca)$importance[2, ] * 100
var_acum <- summary(res_pca)$importance[3, ] * 100
cat(
"Los dos primeros componentes explican conjuntamente ",
round(var_acum[2], 2),
"% de la variabilidad total. Este resultado permite evaluar qué tan adecuadamente ",
"puede representarse la información original mediante un número reducido de dimensiones. ",
"La selección de los componentes se complementa con el análisis de sus cargas y contribuciones, ",
"con el fin de identificar las características que definen cada dimensión."
)Los dos primeros componentes explican conjuntamente 69.82 % de la variabilidad total. Este resultado permite evaluar qué tan adecuadamente puede representarse la información original mediante un número reducido de dimensiones. La selección de los componentes se complementa con el análisis de sus cargas y contribuciones, con el fin de identificar las características que definen cada dimensión.
fviz_pca_var(
res_pca,
col.var = "contrib",
gradient.cols = c("#D95F02", "#1B9E77", "#7570B3"),
repel = TRUE
) +
labs(title = "Contribución de las variables a los componentes")cargas <- as.data.frame(res_pca$rotation[, 1:3])
cargas$variable <- rownames(cargas)
tabla_cargas <- cargas[, c("variable", "PC1", "PC2", "PC3")]
colnames(tabla_cargas) <- c(
"Variable",
"Componente 1",
"Componente 2",
"Componente 3"
)
formato_tabla(
tabla_cargas,
"Cargas de las variables en los tres primeros componentes",
digits = 3
)| Variable | Componente 1 | Componente 2 | Componente 3 | |
|---|---|---|---|---|
| piso | piso | 0.070 | 0.547 | -0.816 |
| estrato | estrato | -0.323 | 0.518 | 0.222 |
| areaconst | areaconst | -0.444 | -0.207 | -0.043 |
| parqueaderos | parqueaderos | -0.407 | 0.221 | 0.193 |
| preciom | preciom | -0.475 | 0.183 | 0.076 |
| banios | banios | -0.467 | -0.121 | -0.205 |
| habitaciones | habitaciones | -0.290 | -0.542 | -0.445 |
Los resultados indican que los dos primeros componentes explican conjuntamente el 69,82% de la variabilidad total, lo que evidencia una adecuada capacidad de síntesis de la información original. En términos prácticos, la estructura del mercado inmobiliario puede representarse mediante dos dimensiones principales sin perder una cantidad significativa de información.
El Componente Principal 1 (49%) está asociado principalmente con las variables precio, área construida, número de baños y parqueaderos. Las cargas observadas sugieren que este eje representa una dimensión de valor inmobiliario y nivel de equipamiento residencial. Las viviendas ubicadas en los extremos de este componente corresponden a inmuebles de mayor tamaño, mejor dotación y precios superiores, mientras que en el extremo opuesto se encuentran viviendas más compactas y de menor valor económico.
El Componente Principal 2 (20,9%) está determinado principalmente por el estrato y el número de piso, en contraposición al número de habitaciones. Esta dimensión refleja diferencias asociadas al contexto socioeconómico y al tipo de desarrollo urbano, distinguiendo viviendas localizadas en estratos superiores y edificaciones verticales frente a inmuebles con configuraciones más orientadas al tamaño familiar.
Estos resultados indican que la heterogeneidad del mercado inmobiliario de Cali se explica fundamentalmente por dos factores: el valor físico-económico de la vivienda y su contexto socioespacial. Este hallazgo resulta especialmente relevante para procesos de valoración, ya que muestra que el precio no depende únicamente del tamaño del inmueble, sino también de variables asociadas al nivel socioeconómico y a las características constructivas de la propiedad.
La elevada contribución conjunta de las variables área construida, precio, baños y parqueaderos sugiere que el mercado residencial se encuentra fuertemente segmentado por atributos de calidad y tamaño de las viviendas. En consecuencia, las estrategias de valoración no deberían sustentarse únicamente en variables socioeconómicas como el estrato, sino incorporar simultáneamente atributos físicos que capturan una proporción importante de la heterogeneidad observada en la oferta.
El objetivo del clustering es segmentar las viviendas en grupos internamente homogéneos y externamente diferenciados. Para evitar que el identificador o variables categóricas codificadas artificialmente influyan sobre las distancias, el agrupamiento se realiza únicamente con variables cuantitativas relevantes.
# Seleccionamos las variables base para el modelo y conservamos p_m2 e id para el perfil
cluster_data_full <- vivienda %>%
select(id, estrato, areaconst, parqueaderos, preciom,
banios, habitaciones, piso) %>%
drop_na()
# Seleccionamos SOLO las variables cuantitativas base para escalar y meter al K-means
cluster_scale <- scale(cluster_data_full)fviz_nbclust(cluster_scale, kmeans, method = "wss") +
geom_vline(xintercept = 3, linetype = 2) +
labs(title = "Método del codo para seleccionar el número de conglomerados",
x = "Número de conglomerados",
y = "Suma de cuadrados intra-grupo")El método del codo evidenció una reducción importante de la variabilidad intra-grupo hasta tres conglomerados, a partir de los cuales la mejora marginal disminuye considerablemente. En consecuencia, se seleccionó una solución de tres segmentos, permitiendo identificar grupos con perfiles claramente diferenciados y utilidad estratégica para la segmentación del mercado inmobiliario.
set.seed(123)
modelo_kmeans <- kmeans(cluster_scale, centers = 3, nstart = 50)
# Asignamos el cluster a la tabla que SÍ contiene p_m2
clustered <- cluster_data_full %>%
mutate(cluster = factor(modelo_kmeans$cluster))
fviz_cluster(modelo_kmeans,
data = cluster_scale,
geom = "point",
ellipse.type = "norm",
ggtheme = theme_minimal()) +
labs(title = "Segmentación de viviendas mediante K-means")perfil_cluster <- clustered %>%
group_by(cluster) %>%
summarise(
viviendas = n(),
estrato_promedio = mean(estrato, na.rm = TRUE),
area_promedio = mean(areaconst, na.rm = TRUE),
precio_promedio = mean(preciom, na.rm = TRUE),
habitaciones_promedio = mean(habitaciones, na.rm = TRUE),
banios_promedio = mean(banios, na.rm = TRUE),
parqueaderos_promedio = mean(parqueaderos, na.rm = TRUE),
piso_promedio = mean(piso, na.rm = TRUE),
.groups = "drop"
)
tabla_perfil <- perfil_cluster
colnames(tabla_perfil) <- c(
"Conglomerado",
"Viviendas",
"Estrato promedio",
"Área promedio (m²)",
"Precio promedio (millones)",
"Habitaciones promedio",
"Baños promedio",
"Parqueaderos promedio",
"Piso promedio"
)
formato_tabla(
tabla_perfil,
"Perfil promedio de los conglomerados",
digits = 2
)| Conglomerado | Viviendas | Estrato promedio | Área promedio (m²) | Precio promedio (millones) | Habitaciones promedio | Baños promedio | Parqueaderos promedio | Piso promedio |
|---|---|---|---|---|---|---|---|---|
| 1 | 1603 | 5.31 | 380.87 | 904.02 | 5.04 | 5.07 | 2.90 | 2.84 |
| 2 | 3600 | 3.82 | 109.16 | 224.94 | 3.30 | 2.24 | 0.74 | 3.36 |
| 3 | 3116 | 5.23 | 144.99 | 433.49 | 3.22 | 3.11 | 1.60 | 4.56 |
Interpretación de los conglomerados
El análisis de conglomerados permitió identificar tres segmentos claramente diferenciados dentro del mercado residencial de Cali. La segmentación se encuentra principalmente determinada por diferencias en área construida, precio, número de baños y disponibilidad de parqueaderos, variables que previamente habían mostrado una elevada contribución dentro del PCA.
Conglomerado 1: Segmento Premium
Este grupo concentra 1.603 viviendas y presenta los mayores niveles de área construida (380,87 m²), precio promedio (904 millones), baños (5,07) y parqueaderos (2,90). Su estrato promedio es 5,31. Estas características reflejan una oferta orientada a hogares de altos ingresos y corresponden al segmento de lujo del mercado residencial.
Conglomerado 2: Segmento Masivo de Precio Accesible
Agrupa 3.600 viviendas y presenta los valores más bajos de precio (224 millones), área (109 m²), baños (2,24) y parqueaderos (0,74). Además registra el menor estrato promedio (3,82). Este conglomerado representa el mercado de mayor volumen y constituye el principal segmento para estrategias orientadas a vivienda de amplio alcance comercial.
Conglomerado 3: Segmento Intermedio Consolidado
Incluye 3.116 viviendas y presenta niveles intermedios de área (145 m²), precio (433 millones) y equipamiento residencial. A pesar de exhibir un estrato promedio similar al del conglomerado 1 (5,23), sus características físicas y económicas son considerablemente menores, lo que evidencia que viviendas ubicadas en contextos socioeconómicos similares pueden presentar perfiles de mercado distintos.
Implicaciones estratégicas
La segmentación obtenida demuestra que el estrato por sí solo no explica completamente el valor inmobiliario. La coexistencia de los conglomerados 1 y 3 en estratos altos evidencia que el tamaño, el equipamiento y las características constructivas generan diferencias significativas dentro de un mismo contexto socioeconómico. Esto abre oportunidades para diseñar estrategias diferenciadas de valoración, comercialización y captación de inmuebles.
perfil_largo <- perfil_cluster %>%
select(cluster, area_promedio, precio_promedio,
habitaciones_promedio, banios_promedio,
parqueaderos_promedio) %>%
pivot_longer(-cluster, names_to = "indicador", values_to = "valor")
ggplot(perfil_largo, aes(x = cluster, y = valor, fill = cluster)) +
geom_col(show.legend = FALSE) +
facet_wrap(~ indicador, scales = "free_y") +
labs(title = "Indicadores promedio por conglomerado",
x = "Conglomerado",
y = "Valor promedio") +
theme_minimal()El análisis de correspondencias permite estudiar asociaciones entre
variables categóricas a partir de tablas de contingencia. En este caso
se consideran especialmente tipo, zona y
barrio, ya que permiten examinar cómo se distribuye la
oferta residencial en el territorio.
En primer lugar, se analiza la distribución espacial de las viviendas según su nivel socioeconómico (estrato).
# Graficar la distribución de viviendas por zona y estrato
vivienda %>%
count(zona, estrato) %>%
ggplot(aes(x = fct_reorder(zona, n), y = n, fill = as.factor(estrato))) +
geom_col(position = "stack", width = 0.7) +
scale_fill_brewer(palette = "Set2", name = "Estrato") +
coord_flip() +
labs(
title = "Distribución de viviendas por zona y estrato",
x = "Zona",
y = "Unidades de vivienda"
) +
theme_minimal(base_size = 12) tabla_estrato_zona <- table(vivienda$zona, vivienda$estrato)
colnames(tabla_estrato_zona) <- paste("Estrato", 3:6)
tabla_estrato_zona##
## Estrato 3 Estrato 4 Estrato 5 Estrato 6
## Zona Centro 105 14 4 1
## Zona Norte 572 407 769 172
## Zona Oeste 54 84 290 770
## Zona Oriente 340 8 2 1
## Zona Sur 382 1616 1685 1043
# Prueba Chi-cuadrado de independencia
chi_estrato_zona <- chisq.test(tabla_estrato_zona)
chi_estrato_zona##
## Pearson's Chi-squared test
##
## data: tabla_estrato_zona
## X-squared = 3830.4, df = 12, p-value < 2.2e-16
La prueba Chi-cuadrado evidenció una asociación altamente significativa entre la zona geográfica y el estrato socioeconómico (χ² = 3830,4; p < 0,001), confirmando que la distribución del nivel socioeconómico no es homogénea dentro de la ciudad.
Las dos primeras dimensiones explican el 97,65% de la inercia total, lo que indica que el mapa factorial representa adecuadamente la estructura de asociación existente entre las categorías analizadas.
El análisis factorial muestra una especialización territorial evidente. La Zona Oeste se encuentra estrechamente asociada con el Estrato 6, consolidándose como el principal mercado de vivienda de alto valor. Por su parte, la Zona Oriente y el Centro muestran proximidad con el Estrato 3, evidenciando una concentración de oferta orientada a segmentos de ingresos medios y bajos. Finalmente, la Zona Sur concentra gran parte de la oferta de los estratos 4 y 5, constituyéndose como el principal corredor residencial de nivel medio y medio alto de la ciudad.
Desde la perspectiva empresarial, estos resultados confirman que la localización geográfica constituye un determinante fundamental de la segmentación inmobiliaria y debe incorporarse explícitamente en los modelos de valoración y en las estrategias de adquisición de inmuebles.
ca_estrato_zona <- CA(tabla_estrato_zona, graph = FALSE)
# Mostrar eigenvalores e inercia explicada
ca_estrato_zona$eig## eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.32215213 69.965515 69.96551
## dim 2 0.12745096 27.680002 97.64552
## dim 3 0.01084108 2.354483 100.00000
# Evaluación de dimensiones e impresión de Biplot
num_dim <- ncol(ca_estrato_zona$row$coord)
if (num_dim >= 2) {
fviz_ca_biplot(
ca_estrato_zona,
axes = c(1, 2),
repel = TRUE,
col.row = "#D95F02",
col.col = "#1B9E77"
) +
labs(
title = "Correspondencia entre zona y estrato",
x = paste0("Dimensión 1 (", round(ca_estrato_zona$eig[1, 2], 1), "%)"),
y = paste0("Dimensión 2 (", round(ca_estrato_zona$eig[2, 2], 1), "%)")
) +
theme_minimal(base_size = 12)
} else {
fviz_ca_row(
ca_estrato_zona,
axes = c(1, 1),
col.row = "#D95F02",
repel = TRUE
) +
labs(
title = "Correspondencia (Unidimensional) entre zona y estrato",
x = paste0("Dimensión 1 (", round(ca_estrato_zona$eig[1, 2], 1), "%)")
) +
theme_minimal(base_size = 12)
}# Gráfico de inercia
fviz_screeplot(ca_estrato_zona, addlabels = TRUE, barfill = "#1B9E77", barcolor = "#1B9E77") +
labs(
title = "Inercia explicada - Zona vs. Estrato",
x = "Dimensiones",
y = "Porcentaje de inercia"
) +
theme_minimal(base_size = 12)
Estos hallazgos sugieren la existencia de procesos de segregación
residencial y diferenciación territorial de la oferta inmobiliaria,
donde determinadas zonas concentran segmentos específicos del
mercado.
A continuación, se evalúa la preferencia de tipo de vivienda (Casa / Apartamento) en los distintos estratos socioeconómicos.
# Distribución de tipos de vivienda según el estrato
ggplot(vivienda, aes(x = as.factor(estrato), fill = tipo)) +
geom_bar(position = "dodge", width = 0.7) +
scale_fill_manual(values = c("Apartamento" = "#1B9E77", "Casa" = "#D95F02")) +
labs(
title = "Distribución de tipo de vivienda por estrato",
x = "Estrato",
y = "Número de viviendas",
fill = "Tipo de Vivienda"
) +
theme_minimal(base_size = 12)#Tabla de contingencia entre tipo de vivienda y estrato
tabla_tipo_estrato <- table(vivienda$tipo, vivienda$estrato)
colnames(tabla_tipo_estrato) <- paste("Estrato", 3:6)
tabla_tipo_estrato##
## Estrato 3 Estrato 4 Estrato 5 Estrato 6
## Apartamento 639 1404 1766 1291
## Casa 814 725 984 696
##
## Pearson's Chi-squared test
##
## data: tabla_tipo_estrato
## X-squared = 224.33, df = 3, p-value < 2.2e-16
La distribución observada muestra que los apartamentos predominan en los estratos 4, 5 y 6, mientras que las casas presentan una participación relativamente mayor en el estrato 3. La prueba Chi-cuadrado confirma que estas diferencias no son producto del azar y reflejan patrones estructurales del mercado residencial.
Este resultado sugiere que la verticalización de la vivienda se encuentra asociada a segmentos socioeconómicos medios y altos, mientras que las viviendas unifamiliares mantienen una presencia importante en los mercados de menor estrato. Para la inmobiliaria, estas diferencias constituyen información relevante para orientar la estructuración del portafolio y definir estrategias de promoción diferenciadas según el público objetivo.
## eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.0269661 100 100
# Gráfico de inercia explicada
fviz_screeplot(ca_tipo_estrato, addlabels = TRUE, barfill = "#D95F02", barcolor = "#D95F02") +
labs(
title = "Inercia explicada - Tipo vs. Estrato",
x = "Dimensiones",
y = "Porcentaje de inercia"
) +
theme_minimal(base_size = 12)Para evaluar la interacción conjunta entre las tres variables categóricas (Zona, Tipo de Vivienda y Estrato), se aplica un Análisis de Correspondencias Múltiples.
# Selección y formateo de datos
vivienda_mca_data <- vivienda %>%
select(zona, estrato, tipo) %>%
mutate(across(everything(), as.factor))
# Ajuste del modelo MCA
mca_resultado <- MCA(vivienda_mca_data, graph = FALSE)
# 1. Varianza explicada (Scree plot)
fviz_screeplot(mca_resultado, addlabels = TRUE, barfill = "#7570B3", barcolor = "#7570B3") +
labs(
title = "Varianza explicada por dimensión (MCA)",
x = "Dimensiones",
y = "Porcentaje de varianza"
) +
theme_minimal(base_size = 12)# 2. Biplot del MCA (Solo mostrando variables para evitar saturación de ggrepel)
fviz_mca_var(
mca_resultado,
repel = TRUE,
col.var = "#D95F02"
) +
labs(
title = "Biplot de Categorías de Variables (MCA)",
x = paste0("Dimensión 1 (", round(mca_resultado$eig[1, 2], 1), "%)"),
y = paste0("Dimensión 2 (", round(mca_resultado$eig[2, 2], 1), "%)")
) +
theme_minimal(base_size = 12)# 3. Asociacion de variables con las dimensiones
fviz_mca_var(
mca_resultado,
choice = "mca.cor",
repel = TRUE,
col.var = "#1B9E77"
) +
labs(
title = "Asociacion de las variables con las dimensiones principales",
x = "Dimensión 1",
y = "Dimensión 2"
) +
theme_minimal(base_size = 12)
El MCA permitió analizar simultáneamente las relaciones entre zona,
estrato y tipo de vivienda. Las dos primeras dimensiones explican
aproximadamente el 38% de la variabilidad total, porcentaje aceptable
considerando la naturaleza categórica de los datos.
El mapa factorial evidencia patrones consistentes con los resultados obtenidos previamente en el análisis de correspondencias simple, destacándose la proximidad entre la Zona Oeste y el Estrato 6, así como la asociación entre la Zona Oriente y el Estrato 3.
La proximidad entre determinadas categorías indica que las características socioeconómicas y territoriales no son independientes, sino que forman estructuras de mercado relativamente estables. En consecuencia, las decisiones de inversión y valoración inmobiliaria deben considerar simultáneamente la localización, el estrato y el tipo de vivienda, en lugar de analizarlos de manera aislada.
La base contiene coordenadas de localización, por lo que se incorpora una representación geográfica como complemento de los análisis anteriores. La visualización permite observar si determinados segmentos de vivienda se concentran territorialmente.
Para evitar depender del orden de las filas, se construye la asignación a partir de un identificador común:
ids_cluster <- vivienda %>%
select(id, estrato, areaconst, parqueaderos, preciom, banios,
habitaciones, piso) %>%
drop_na() %>%
mutate(cluster = factor(modelo_kmeans$cluster)) %>%
select(id, cluster)
mapa_data <- vivienda %>%
mutate(
longitud = as.numeric(longitud),
latitud = as.numeric(latitud)
) %>%
left_join(ids_cluster, by = "id") %>%
filter(!is.na(longitud), !is.na(latitud), !is.na(cluster))
mapa_sf <- st_as_sf(mapa_data,
coords = c("longitud", "latitud"),
crs = 4326)
ggplot(mapa_sf) +
geom_sf(aes(color = cluster), alpha = 0.55, size = 1.3) +
labs(title = "Distribución espacial de los conglomerados residenciales",
color = "Conglomerado") +
theme_minimal()La distribución espacial de los conglomerados evidencia que los segmentos identificados no se encuentran distribuidos aleatoriamente en el territorio. Se observan concentraciones geográficas diferenciadas que sugieren procesos de especialización residencial dentro de la ciudad. Este resultado refuerza la importancia de incorporar simultáneamente atributos físicos y variables de localización en los procesos de valoración inmobiliaria y selección de oportunidades de inversión.
Los cuatro enfoques utilizados responden preguntas diferentes y, por ello, deben interpretarse de forma complementaria:
La principal contribución de este estudio consiste en demostrar que el mercado inmobiliario residencial de Cali presenta una estructura altamente segmentada, tanto desde el punto de vista físico como socioespacial. La combinación de técnicas multivariadas permitió identificar patrones que no son evidentes mediante análisis descriptivos tradicionales.
El PCA mostró que la mayor parte de la variabilidad del mercado se encuentra explicada por dos dimensiones fundamentales: el valor físico-económico de la vivienda y el contexto socioeconómico asociado a su localización. Estas dimensiones sintetizan los principales factores que diferencian la oferta residencial.
El análisis de conglomerados evidenció la existencia de tres segmentos claramente diferenciados: un mercado premium de alta valorización, un mercado masivo orientado a vivienda de precio accesible y un mercado intermedio asociado a hogares de ingresos medios-altos. Esta clasificación proporciona una base objetiva para la segmentación comercial y la priorización de inversiones.
Los análisis de correspondencias confirmaron que la distribución territorial de la vivienda está estrechamente relacionada con el estrato socioeconómico y el tipo de inmueble. La localización emerge como un factor estructural del mercado y constituye un elemento determinante para la valoración y comercialización de propiedades.
En conjunto, los resultados evidencian que las decisiones inmobiliarias más eficientes requieren integrar simultáneamente variables físicas, económicas y espaciales, permitiendo una comprensión más robusta de la dinámica del mercado residencial urbano
Segmentar la oferta: utilizar los conglomerados para construir portafolios comerciales diferenciados y evitar estrategias homogéneas para propiedades con perfiles muy distintos.
Priorizar variables de valor: incorporar el precio por metro cuadrado junto con área, estrato y características físicas para comparar oportunidades de forma más consistente que utilizando solamente el precio total.
Incorporar el componente territorial: cruzar los segmentos obtenidos con zona y barrio para identificar dónde se concentra cada perfil de vivienda y apoyar decisiones de adquisición o comercialización.
Orientar la estrategia comercial: utilizar las asociaciones encontradas mediante correspondencias para adaptar la oferta a las características predominantes de cada territorio.
Fortalecer el uso de datos geográficos: integrar los mapas a tableros de gestión para monitorear concentración de inventario, precios por metro cuadrado y evolución de segmentos en el territorio.
Mejorar la calidad de la información: validar con el área de negocio el significado de los valores faltantes de parqueaderos y mantener trazabilidad de cualquier imputación antes de utilizar estos resultados para decisiones de inversión.