Este informe analiza 8.322 registros de oferta residencial urbana con el fin de identificar la estructura del mercado y orientar decisiones de compra, venta y valoración. Se aplicaron cuatro técnicas de análisis multivariado: componentes principales, conglomerados, correspondencias simples y múltiples, y visualización geográfica.
Los cinco hallazgos que sostienen las recomendaciones son:
El precio por metro cuadrado es independiente del tamaño de la vivienda. La correlación de esta variable con el primer componente principal, el eje de tamaño que concentra el 63,4 % de la varianza, es de apenas 0,021. Comprar grande no implica comprar caro por metro.
Existe un segmento de “metro cuadrado barato” invisible al análisis univariado. Un conglomerado que representa el 9,1 % de la oferta reúne casas de 300 m² y 7 habitaciones que se transan a 1,46 millones por m², frente a 2,67 del apartamento estándar. Es la mayor oportunidad de arbitraje detectada.
El precio total y el precio por metro cuadrado responden a factores distintos. La estructura del producto explica el 69,9 % de la varianza del precio total pero solo el 13,0 % de la del precio unitario; en esta última mandan el barrio (45,8 %) y el estrato (32,2 %). Valorar con un solo criterio deja la mitad del fenómeno sin explicar.
El mercado está fuertemente segregado en el eje oriente–occidente. El 96,8 % de la oferta de Zona Oriente es estrato 3; el 64,6 % de Zona Oeste es estrato 6. Zona Sur es la única zona con perfil equilibrado.
La base no cubre estratos 1 y 2. Toda conclusión aplica al mercado formal de estratos 3 a 6. Esta limitación se detalla en la sección de alcance.
Una empresa inmobiliaria requiere comprender en profundidad el mercado de viviendas urbanas para tomar decisiones estratégicas más informadas sobre adquisición, venta y valoración de propiedades. La empresa dispone de una base extensa de propiedades residenciales, pero los indicadores descriptivos tradicionales (precio medio, área media) no revelan la estructura subyacente de la oferta ni permiten segmentarla de forma accionable.
Realizar un análisis integral y multidimensional de la base de datos de oferta residencial que permita identificar patrones, relaciones y segmentaciones relevantes para la toma de decisiones estratégicas.
| # | Objetivo | Técnica |
|---|---|---|
| 1 | Reducir la dimensionalidad del conjunto de variables cuantitativas e identificar las características que gobiernan la variación de precios y oferta | Análisis de Componentes Principales |
| 2 | Agrupar las propiedades en segmentos homogéneos y caracterizar las dinámicas de oferta por zona y estrato | Análisis de Conglomerados |
| 3 | Examinar la asociación entre las variables categóricas (tipo de vivienda, zona, barrio y estrato) e identificar patrones de comportamiento de la oferta | Análisis de Correspondencias simples y múltiples |
| 4 | Comunicar los hallazgos mediante gráficos, mapas y recursos visuales orientados a la dirección | Visualización de resultados |
Los datos provienen de avisos publicados en el portal OLX, obtenidos
mediante un procedimiento de web scraping, y se distribuyen en
el paquete paqueteMODELOS. Se trata por tanto de una
muestra de oferta publicada, no de transacciones
cerradas: los precios son precios de lista.
# El dataset se carga desde el archivo .rda del paquete del curso. Se evita
# instalar el paquete completo porque arrastra dependencias (summarytools,
# GGally, gridExtra) que este informe no utiliza.
ruta <- file.path("data", "vivienda.rda")
if (!file.exists(ruta)) {
dir.create("data", showWarnings = FALSE)
download.file(
"https://github.com/centromagis/paqueteMODELOS/raw/main/data/vivienda.rda",
ruta, mode = "wb", quiet = TRUE
)
}
entorno <- new.env(); load(ruta, envir = entorno)
crudo <- as.data.frame(entorno$vivienda)
dim(crudo)
## [1] 8322 13
La base contiene 8.322 registros y 13 variables:
| Diccionario de variables | |||
| Variable | Tipo | Descripción | Rol |
|---|---|---|---|
| id | Numérica | Identificador del aviso | Identificador |
| zona | Categórica | Zona de la ciudad (5 niveles) | Suplementaria / AC |
| piso | Categórica | Piso en que se ubica el inmueble | Excluida |
| estrato | Ordinal | Estrato socioeconómico | Suplementaria / AC |
| preciom | Numérica | Precio de lista en millones de pesos | Activa (ACP) |
| areaconst | Numérica | Área construida en m² | Activa (ACP) |
| parqueaderos | Numérica | Número de parqueaderos | Activa (ACP) |
| banios | Numérica | Número de baños | Activa (ACP) |
| habitaciones | Numérica | Número de habitaciones | Activa (ACP) |
| tipo | Categórica | Casa o Apartamento | Suplementaria / AC |
| barrio | Categórica | Barrio (436 niveles) | AC |
| longitud | Numérica | Coordenada geográfica | Visualización |
| latitud | Numérica | Coordenada geográfica | Visualización |
El rango de coordenadas (longitud entre −76,59 y −76,46; latitud entre 3,33 y 3,50) sitúa la totalidad de la oferta en Santiago de Cali.
El tratamiento de los datos faltantes es la decisión metodológica de mayor impacto en este análisis, y se documenta en detalle porque condiciona todos los resultados posteriores.
| Valores faltantes en la base cruda | ||
| Variable | Faltantes | % del total |
|---|---|---|
| piso | 2638 | 31,70 |
| parqueaderos | 1605 | 19,29 |
| id | 3 | 0,04 |
| zona | 3 | 0,04 |
| estrato | 3 | 0,04 |
| areaconst | 3 | 0,04 |
| banios | 3 | 0,04 |
| habitaciones | 3 | 0,04 |
| tipo | 3 | 0,04 |
| barrio | 3 | 0,04 |
| longitud | 3 | 0,04 |
| latitud | 3 | 0,04 |
| preciom | 2 | 0,02 |
piso se excluye del análisisLa hipótesis natural es que piso falta porque las casas
no tienen número de piso. Los datos la refutan:
| Faltantes de `piso` según tipo de vivienda | |||
| El 61,0 % de las casas sí registra piso: el faltante no es estructural | |||
| tipo | n | Faltantes | % faltante |
|---|---|---|---|
| Apartamento | 5100 | 1381 | 27,1 |
| Casa | 3219 | 1254 | 39,0 |
Los apartamentos presentan 27,1 % de faltantes y las casas 39,0 %. Si el mecanismo fuera estructural, las casas estarían al 100 %. Se trata de captura incompleta sin patrón aprovechable. Con 31,7 % de ausencia y sin mecanismo identificable, la variable se excluye en lugar de imputarse.
parqueaderos se imputa en ceroAquí el mecanismo sí es identificable, y la evidencia es consistente:
| Perfil de los registros con y sin dato de parqueaderos | ||||
| Los registros sin dato son sistemáticamente más baratos y más pequeños | ||||
| Parqueaderos | n | Precio mediano (M) | Área mediana (m²) | Baños medianos |
|---|---|---|---|---|
| Faltante | 1.602 | 179 | 90 | 2 |
| Observado | 6.717 | 355 | 130 | 3 |
Tres piezas de evidencia convergen:
La lectura es que el dato ausente significa “sin parqueadero”. Se imputa cero.
Por qué no se eliminan esos registros. El mecanismo de ausencia no es aleatorio (MNAR): está ligado al precio y al estrato. Eliminar por lista las 1.605 filas afectadas equivaldría a borrar sistemáticamente el extremo bajo del mercado y sesgar al alza todos los resultados posteriores. El Anexo A verifica que la estructura factorial es robusta a esta decisión.
bitacora <- tibble(paso = character(), detalle = character(),
n = integer(), removidas = integer())
registrar <- function(bit, paso, detalle, n_antes, n_ahora) {
bind_rows(bit, tibble(paso = paso, detalle = detalle,
n = n_ahora, removidas = n_antes - n_ahora))
}
n0 <- nrow(crudo)
bitacora <- registrar(bitacora, "Base cruda", "Registros originales", n0, n0)
# 1. Filas vacías remanentes de la exportación del archivo de origen.
d <- crudo |> filter(rowSums(is.na(crudo)) <= 8)
bitacora <- registrar(bitacora, "Registros vacíos",
"Filas sin información utilizable", n0, nrow(d))
# 2. Cero baños o cero habitaciones no es plausible en una vivienda en venta:
# se tratan como errores de captura, no como valores reales.
n_prev <- nrow(d)
d <- d |> filter(banios > 0, habitaciones > 0)
bitacora <- registrar(bitacora, "Ceros implausibles",
"banios = 0 o habitaciones = 0", n_prev, nrow(d))
# 3. Imputación justificada en la sección anterior.
d <- d |> mutate(
parqueaderos_imputado = is.na(parqueaderos),
parqueaderos = replace_na(parqueaderos, 0)
)
# 4. `piso` se descarta: 31,7 % faltante sin mecanismo estructural.
d <- d |> select(-piso)
# 5. Registros incompletos remanentes en las variables del análisis.
activas_todas <- c("preciom", "areaconst", "parqueaderos", "banios",
"habitaciones", "estrato", "zona", "tipo", "barrio",
"longitud", "latitud")
n_prev <- nrow(d)
d <- d |> filter(if_all(all_of(activas_todas), ~ !is.na(.x)))
bitacora <- registrar(bitacora, "Casos incompletos",
"NA en alguna variable de análisis", n_prev, nrow(d))
# 6. Variables derivadas y tipificación.
d <- d |> mutate(
tipo = factor(tipo),
zona = factor(zona),
estrato = factor(estrato, levels = sort(unique(estrato)), ordered = TRUE),
estrato_num = as.numeric(as.character(estrato)),
ppm2 = preciom / areaconst,
# Marca de plausibilidad, no filtro: estos registros permanecen en el
# análisis y su influencia se examina vía contribuciones individuales.
ppm2_atipico = ppm2 < 0.5 | ppm2 > 8
)
| Bitácora de depuración | |||
| Base final: 8.243 registros (99,1 % de la base cruda) | |||
| Paso | Detalle | N resultante | Removidas |
|---|---|---|---|
| Base cruda | Registros originales | 8.322 | 0 |
| Registros vacíos | Filas sin información utilizable | 8.319 | 3 |
| Ceros implausibles | banios = 0 o habitaciones = 0 | 8.243 | 76 |
| Casos incompletos | NA en alguna variable de análisis | 8.243 | 0 |
La depuración conserva el 99,1 % de los registros
originales. La decisión sobre parqueaderos es la razón:
preserva 1.555 viviendas que la eliminación por lista habría
descartado.
Antes de interpretar cualquier resultado, tres limitaciones acotan el alcance de las conclusiones:
| Cobertura por estrato socioeconómico | ||
| No hay registros de estratos 1 y 2 en la base | ||
| Estrato | Registros | % |
|---|---|---|
| 3 | 1.432 | 17,4 |
| 4 | 2.106 | 25,5 |
| 5 | 2.728 | 33,1 |
| 6 | 1.977 | 24,0 |
barrio no está anidado en
zona. 93 de los 433 barrios aparecen asignados a
más de una zona, lo que indica inconsistencia en la georreferenciación
del origen. Por esta razón los análisis por barrio se restringen a los
barrios con volumen suficiente y se interpretan con cautela.| Técnica | Función | Papel en el análisis |
|---|---|---|
| Componentes principales (ACP) | FactoMineR::PCA() |
Reducción de dimensionalidad sobre 5 variables cuantitativas
estandarizadas, con estrato y precio por m² como
suplementarias cuantitativas y zona y tipo
como suplementarias cualitativas |
| Conglomerados no jerárquicos | stats::kmeans() |
Segmentación sobre las puntuaciones factoriales retenidas |
| Conglomerados jerárquicos | stats::hclust(), Ward.D2 |
Dendrograma y validación cruzada de la partición |
| Correspondencias simples (AC) | FactoMineR::CA() |
Asociación zona × estrato y barrio × (tipo·estrato) |
| Correspondencias múltiples (ACM) | FactoMineR::MCA() |
Integración de las seis variables categóricas, con corrección de Benzécri |
| Visualización geográfica | leaflet |
Proyección espacial de los segmentos |
Todas las variables cuantitativas se estandarizan
antes del ACP (scale.unit = TRUE), condición necesaria dado
que precio (millones), área (m²) y conteos operan en escalas
incomparables.
Las tres variables monetarias y de tamaño presentan asimetría positiva pronunciada, con una cola larga hacia valores altos. La mediana de precio por metro cuadrado se sitúa en 2,65 millones.
La oferta se concentra territorialmente: Zona Sur reúne el 57 % de los avisos, mientras Zona Centro apenas alcanza el 1,5 %.
Dos lecturas orientan el ACP:
habitaciones se comporta distinto:
correlaciona 0,52 con área pero solo 0,26 con precio y −0,07 con
estrato. Más habitaciones no implica mayor precio ni mejor
estrato. Esta anomalía será el segundo componente.Se emplean cinco variables activas cuantitativas: precio, área construida, parqueaderos, baños y habitaciones. Se incorporan como suplementarias cuantitativas el estrato y el precio por m², y como suplementarias cualitativas la zona y el tipo de vivienda.
La elección de dejar estrato fuera del conjunto activo
es deliberada: permite construir los ejes exclusivamente a partir de los
atributos físicos y de precio del inmueble, y luego verificar de
forma externa si la estratificación socioeconómica se alinea
con ellos. Si el estrato fuera activo, esa validación sería
circular.
# Los nombres se humanizan en la entrada: FactoMineR los usa como etiqueta en
# el círculo de correlaciones, las tablas de cargas y las contribuciones.
X <- d |> select(
`Precio` = preciom,
`Área` = areaconst,
`Parqueaderos` = parqueaderos,
`Baños` = banios,
`Habitaciones` = habitaciones,
`Estrato` = estrato_num,
`Precio por m²` = ppm2,
zona, tipo
)
acp <- PCA(X, quanti.sup = 6:7, quali.sup = 8:9,
scale.unit = TRUE, ncp = 5, graph = FALSE)
| Descomposición de la varianza | |||
| Las dos primeras componentes retienen el 81,83 % de la información | |||
| Componente | Autovalor | % varianza | % acumulado |
|---|---|---|---|
| comp 1 | 3,172 | 63,432 | 63,432 |
| comp 2 | 0,920 | 18,394 | 81,827 |
| comp 3 | 0,407 | 8,136 | 89,962 |
| comp 4 | 0,314 | 6,281 | 96,244 |
| comp 5 | 0,188 | 3,756 | 100,000 |
Los criterios de selección no coinciden, y la discrepancia merece explicitarse:
| Criterio | Resultado | Componentes |
|---|---|---|
| Kaiser (λ > 1) | Solo Dim 1 supera la unidad (λ₂ = 0,920) | 1 |
| Codo del sedimento | Quiebre nítido después de Dim 2 | 2 |
| Varianza acumulada ≥ 80 % | Se alcanza 81,83 % con dos componentes | 2 |
| Interpretabilidad | Dim 2 tiene lectura sustantiva clara | 2 |
Se retienen dos componentes. El criterio de Kaiser sugeriría una sola, pero el segundo autovalor (0,920) queda a un 8 % del umbral, aporta 18,4 puntos de varianza y, como se muestra enseguida, admite una interpretación económica directa. Descartarlo por un margen tan estrecho eliminaría el eje que distingue la gama de la vivienda. La convergencia de los otros tres criterios sostiene la decisión.
| Cargas, calidad de representación y contribuciones | ||||||
| Variables activas sobre las dos componentes retenidas | ||||||
| Variable | Carga Dim1 | Carga Dim2 | Cos² Dim1 | Cos² Dim2 | Contrib Dim1 (%) | Contrib Dim2 (%) |
|---|---|---|---|---|---|---|
| Precio | 0,848 | −0,340 | 0,719 | 0,116 | 22,67 | 12,56 |
| Área | 0,866 | 0,105 | 0,750 | 0,011 | 23,64 | 1,20 |
| Parqueaderos | 0,722 | −0,514 | 0,521 | 0,264 | 16,43 | 28,71 |
| Baños | 0,885 | 0,132 | 0,783 | 0,017 | 24,68 | 1,88 |
| Habitaciones | 0,631 | 0,715 | 0,399 | 0,512 | 12,57 | 55,65 |
Concentra el 63,4 % de la varianza. Las cinco variables activas cargan positivamente y con magnitudes similares: baños (0,885), área (0,866), precio (0,848), parqueaderos (0,722) y habitaciones (0,631). Las contribuciones se reparten de forma equilibrada, entre 12,6 % y 24,7 %.
Es un factor de tamaño general: viviendas grandes,
caras y bien equipadas en el extremo positivo; pequeñas y económicas en
el negativo. La variable suplementaria tipo lo confirma con
contundencia: Casa proyecta en +1,131 y Apartamento en −0,706, con
valores-test de ±45,6.
Aporta el 18,4 %. Aquí las cargas se oponen: habitaciones carga +0,715 (contribuye el 55,7 % del eje) frente a parqueaderos −0,514 (28,7 %) y precio −0,340 (12,6 %).
La proyección de las variables suplementarias revela el significado del eje:
| Variables suplementarias cuantitativas | ||
| El precio por m² es ortogonal a la Dimensión 1 | ||
| Variable | Dim 1 | Dim 2 |
|---|---|---|
| Estrato | 0,459 | −0,487 |
| Precio por m² | 0,021 | −0,564 |
Este es el hallazgo central del análisis. El precio por metro cuadrado correlaciona 0,021 con la Dimensión 1, es decir, resulta ortogonal al tamaño, y −0,564 con la Dimensión 2. El estrato sigue el mismo patrón: 0,459 y −0,487.
La conclusión de negocio es directa: el tamaño de una vivienda no informa sobre su valor unitario. Una casa de 400 m² y un apartamento de 60 m² pueden tener el mismo precio por metro. Lo que sí discrimina el valor unitario es la posición en el segundo eje: el polo negativo (pocas habitaciones, muchos parqueaderos, estrato alto) concentra el metro cuadrado caro, y el polo positivo (muchas habitaciones, sin parqueadero, estrato bajo) el metro cuadrado barato.
La nube presenta una concentración marcada en el cuadrante inferior izquierdo, donde se ubica la vivienda pequeña de gama media, con dispersión creciente hacia la derecha. Esa forma de abanico indica que la oferta es mucho más heterogénea en el segmento grande que en el pequeño: los apartamentos compactos son un producto estandarizado, las casas grandes no.
Las elipses se solapan de forma considerable en el eje vertical pero
se separan en el horizontal, lo que confirma que tipo es
esencialmente una manifestación del tamaño y aporta poco a la gama.
La segmentación se realiza sobre las puntuaciones factoriales de las dos componentes retenidas, no sobre las variables originales. Esta decisión tiene dos ventajas: elimina la redundancia entre variables fuertemente correlacionadas, que en las distancias euclidianas equivaldría a ponderar el tamaño por duplicado, y filtra el 18,2 % de varianza residual atribuible a ruido.
S <- acp$ind$coord[, 1:2]
Se contrastan tres criterios de validación interna sobre
k de 2 a 8.
| Criterios de validación por número de conglomerados | |||
| Los índices favorecen k = 2; se adopta k = 4 por criterio sustantivo | |||
| k | Silueta media | Calinski-Harabasz | Reducción de inercia (%) |
|---|---|---|---|
| 2 | 0,533 | 8.796,8 | 51,6 |
| 3 | 0,474 | 8.005,9 | 29,8 |
| 4 | 0,465 | 8.437,1 | 27,7 |
| 5 | 0,424 | 8.154,7 | 17,9 |
| 6 | 0,411 | 7.891,4 | 14,3 |
| 7 | 0,375 | 7.825,5 | 13,6 |
| 8 | 0,387 | 7.639,2 | 10,6 |
Los índices y la utilidad de negocio no coinciden, y conviene decirlo con claridad. La silueta media es máxima en k = 2 (0,533) y el índice de Calinski-Harabasz también (8.796,8). Sin embargo, k = 2 produce una partición trivial, viviendas grandes frente a viviendas pequeñas, que ya está capturada por la primera componente y no aporta información accionable.
Se adopta k = 4 sobre la base de tres argumentos:
La partición resultante se valida además con un método independiente en el Anexo B.
set.seed(2026)
km <- kmeans(S, centers = 4, nstart = 50, iter.max = 100)
# Los conglomerados se reordenan y nombran por precio mediano ascendente, de
# modo que la numeración tenga significado y sea estable entre ejecuciones.
orden <- d |>
mutate(cl = km$cluster) |>
group_by(cl) |>
summarise(p = median(preciom), .groups = "drop") |>
arrange(p) |>
pull(cl)
etiquetas <- c("S1 · Apartamento estándar", "S2 · Metro cuadrado barato",
"S3 · Media-alta consolidada", "S4 · Alto standing")
d$segmento <- factor(match(km$cluster, orden), levels = 1:4, labels = etiquetas)
round(km$betweenss / km$totss, 3)
## [1] 0.754
La partición explica el 75,4 % de la inercia total.
| Perfil de los cuatro segmentos | ||||||||||
| Medianas por segmento, ordenados por precio ascendente | ||||||||||
| Segmento | n | % | Precio (M) | Área (m²) | Precio/m² | Hab. | Baños | Parq. | % Casa | Estrato modal |
|---|---|---|---|---|---|---|---|---|---|---|
| S1 · Apartamento estándar | 4.151 | 50,4 | 220 | 80 | 2,67 | 3 | 2 | 1 | 17,0 | 4 |
| S2 · Metro cuadrado barato | 751 | 9,1 | 430 | 300 | 1,46 | 7 | 5 | 1 | 97,5 | 3 |
| S3 · Media-alta consolidada | 2.488 | 30,2 | 480 | 172 | 2,94 | 4 | 4 | 2 | 45,3 | 6 |
| S4 · Alto standing | 853 | 10,3 | 1.150 | 363 | 2,95 | 4 | 5 | 4 | 71,2 | 6 |
S1 · Apartamento estándar: 50,4 % de la oferta. Es el producto masivo del mercado: 80 m², 3 habitaciones, 2 baños, 220 millones, 83 % apartamentos, estrato modal 4. Todos sus indicadores físicos están por debajo de la media, pero su precio por m² (2,67) es prácticamente el del mercado.
S2 · Metro cuadrado barato: 9,1 % de la oferta y el hallazgo más relevante del análisis. Reúne casas (97,5 % del segmento) de 300 m² y 7 habitaciones que se ofertan a 430 millones. El resultado es un precio por metro cuadrado de 1,46 millones, un 45 % por debajo del apartamento estándar pese a cuadruplicar su tamaño. Se concentra en estrato 3 (40,5 %) y sobrerrepresenta Zona Oriente (18,0 % frente al 4,3 % de S1).
S3 · Media-alta consolidada: 30,2 % de la oferta, el segundo bloque en volumen. 172 m², 480 millones y reparto equilibrado entre casa y apartamento (45,3 % casas). Su oferta se distribuye casi por partes iguales entre estrato 5 (38,9 %) y estrato 6 (41,9 %): es el segmento donde la clase media alta y la vivienda de gama superior compiten por el mismo comprador.
S4 · Alto standing: 10,3 % de la oferta. 363 m², 1.150 millones, 4 parqueaderos, estrato 6 en el 75,7 % de los casos. Se concentra en Zona Oeste (28,1 %) y Zona Sur (61,5 %).
Los paneles muestran que la partición corta principalmente a lo largo de la Dimensión 1, con S2 desplazándose además hacia el extremo superior de la Dimensión 2, el polo de “muchas habitaciones, metro cuadrado barato”. Es exactamente la firma que anticipaba el ACP.
Antes de proyectar, se verifica que exista asociación que valga la pena describir.
| Contrastes de independencia | |||||
| Las tres asociaciones son significativas; zona × estrato es la más intensa | |||||
| Tabla | Chi² | gl | Valor p | V de Cramér | Inercia total |
|---|---|---|---|---|---|
| zona × tipo | 688,2 | 4 | < 1e-16 | 0,2889 | 0,0835 |
| zona × estrato | 3.801,8 | 12 | < 1e-16 | 0,3921 | 0,4612 |
| tipo × estrato | 215,4 | 3 | < 1e-16 | 0,1617 | 0,0261 |
Las tres asociaciones son estadísticamente significativas. La intensidad, sin embargo, difiere: la V de Cramér va de 0,162 en tipo × estrato a 0,392 en zona × estrato, que además concentra una inercia total de 0,4612, más de cinco veces la de zona × tipo. El análisis se centra por tanto en esta última tabla.
| Perfiles fila: distribución del estrato dentro de cada zona | ||||
| Porcentajes por fila. La última línea es el perfil medio de referencia | ||||
| Zona |
Estrato
|
|||
|---|---|---|---|---|
| 3 | 4 | 5 | 6 | |
| Zona Centro | 84,3 | 11,6 | 3,3 | 0,8 |
| Zona Norte | 30,0 | 20,9 | 40,1 | 9,0 |
| Zona Oeste | 4,4 | 7,0 | 24,1 | 64,6 |
| Zona Oriente | 96,8 | 2,3 | 0,6 | 0,3 |
| Zona Sur | 8,0 | 34,2 | 35,7 | 22,1 |
| Perfil medio | 17,4 | 25,5 | 33,1 | 24,0 |
Los perfiles fila revelan una segregación extrema. Zona Oriente concentra el 96,8 % de su oferta en estrato 3, frente a un perfil medio de 17,4 %, y Zona Oeste el 64,6 % en estrato 6, contra un promedio de 24,0 %. Zona Sur es la única con un perfil próximo al medio en las cuatro categorías.
ca_ze <- CA(tb_ze, graph = FALSE)
| Descomposición de la inercia | |||
| Dos dimensiones retienen el 97,59 % de la asociación | |||
| Dimensión | Autovalor | % de inercia | % acumulado |
|---|---|---|---|
| dim 1 | 0,3222 | 69,85 | 69,85 |
| dim 2 | 0,1279 | 27,73 | 97,59 |
| dim 3 | 0,0111 | 2,41 | 100,00 |
Dos dimensiones bastan: retienen el 97,59 % de la inercia total. La representación plana es prácticamente exhaustiva.
| Coordenadas, contribuciones y calidad de representación | |||||
| Filas (zonas) y columnas (estratos) del análisis de correspondencias | |||||
| Categoría | Dim 1 | Dim 2 | Contrib. Dim 1 (%) | Contrib. Dim 2 (%) | Cos² plano |
|---|---|---|---|---|---|
| Zona Centro | 1,720 | 0,364 | 13,5 | 1,5 | 0,982 |
| Zona Norte | 0,398 | −0,142 | 11,3 | 3,6 | 0,856 |
| Zona Oeste | −0,573 | 0,783 | 14,7 | 69,1 | 0,999 |
| Zona Oriente | 2,018 | 0,544 | 52,9 | 9,7 | 0,994 |
| Zona Sur | −0,207 | −0,190 | 7,6 | 16,1 | 0,956 |
| Estrato 3 | 1,189 | 0,210 | 76,3 | 6,0 | 1,000 |
| Estrato 4 | −0,154 | −0,381 | 1,9 | 29,0 | 0,899 |
| Estrato 5 | −0,129 | −0,205 | 1,7 | 10,9 | 0,762 |
| Estrato 6 | −0,520 | 0,537 | 20,1 | 54,1 | 0,999 |
Dimensión 1 (69,9 %): eje de segregación socioeconómica. Está dominada por Zona Oriente (contribuye el 52,9 %) y el estrato 3 (76,3 %), ambos en el extremo positivo. Opone las zonas de estrato bajo al resto del mercado. La calidad de representación es excelente para Oriente (cos² = 0,926) y Centro (0,940).
Dimensión 2 (27,7 %): eje de la élite occidental. Zona Oeste contribuye el 69,1 % y el estrato 6 el 54,1 %, opuestos al estrato 4. Este eje separa la vivienda de estrato máximo del bloque intermedio. Nótese que Zona Oeste tiene cos² de solo 0,349 en la Dimensión 1 pero 0,650 en la Dimensión 2: es un fenómeno del segundo eje, y leerla sobre el primero sería un error de interpretación.
Zona Sur ocupa una posición próxima al origen (−0,207; −0,190). En análisis de correspondencias, la proximidad al origen significa un perfil semejante al promedio: Zona Sur es el mercado generalista, sin especialización por estrato. Concentra además el 57 % del volumen total.
Para incorporar el barrio, una variable con 433 niveles, se cruzan los barrios con volumen suficiente contra una variable compuesta que combina tipo de vivienda y estrato, de modo que ambas dimensiones del enunciado se analicen simultáneamente.
barrios_frec <- d |> count(barrio) |> filter(n >= 30) |> pull(barrio)
db <- d |>
filter(barrio %in% barrios_frec) |>
mutate(perfil = droplevels(interaction(tipo, estrato, sep = "-")))
tb_be <- table(db$barrio, db$perfil)
tb_be <- tb_be[rowSums(tb_be) > 0, colSums(tb_be) > 0]
ca_be <- CA(tb_be, graph = FALSE)
dim(tb_be)
## [1] 55 8
El subconjunto abarca 55 barrios que concentran el 75,1 % de la oferta total.
Nota técnica. El contraste χ² sobre esta tabla emite una advertencia por frecuencias esperadas bajas en algunas celdas. Esto afecta la validez del valor p, no la del análisis de correspondencias: la técnica es descriptiva y no requiere supuestos distribucionales. La inercia y las proyecciones siguen siendo interpretables.
Las dos primeras dimensiones retienen el 61 % de la inercia. La estructura es de dos polos diferenciados:
La lectura para la empresa es que el mercado de barrios no se ordena en un único gradiente de precio, sino en dos especializaciones independientes: unos barrios se definen por su oferta premium y otros por su oferta de estrato 3, y entre ambos polos queda un espacio central de barrios no especializados.
El ACM integra las seis variables categóricas en un único espacio, incorporando los rangos de precio, área y habitaciones discretizados por cuartiles.
dm <- d |>
mutate(
r_precio = cut(preciom, breaks = quantile(preciom, 0:4 / 4), include.lowest = TRUE,
labels = c("P: bajo", "P: medio-bajo", "P: medio-alto", "P: alto")),
r_area = cut(areaconst, breaks = quantile(areaconst, 0:4 / 4), include.lowest = TRUE,
labels = c("A: chica", "A: media-chica", "A: media-grande", "A: grande")),
r_hab = cut(habitaciones, breaks = c(0, 2, 3, 4, 10),
labels = c("H: 1-2", "H: 3", "H: 4", "H: 5+"))
) |>
select(tipo, zona, estrato, r_precio, r_area, r_hab)
acm <- MCA(dm, ncp = 5, graph = FALSE)
Los porcentajes de inercia brutos del ACM son sistemáticamente pesimistas: la codificación disyuntiva introduce inercia artificial que no corresponde a estructura real. La corrección de Benzécri descuenta ese componente.
| Inercia bruta frente a inercia corregida | ||||
| Con la corrección de Benzécri, dos dimensiones explican el 87,65 % | ||||
| Dimensión | Autovalor | % bruto | % Benzécri | % Benzécri acumulado |
|---|---|---|---|---|
| Dim 1 | 0,4905 | 17,31 | 67,35 | 67,35 |
| Dim 2 | 0,3444 | 12,16 | 20,30 | 87,65 |
| Dim 3 | 0,2883 | 10,18 | 9,51 | 97,16 |
| Dim 4 | 0,2302 | 8,12 | 2,59 | 99,75 |
Sin corrección, las dos primeras dimensiones parecerían retener apenas el 29,5 % de la información. Corregidas, retienen el 87,65 %. Reportar el valor bruto llevaría a subestimar gravemente la calidad de la representación.
La descomposición es nítida y constituye el tercer hallazgo del informe:
| Variable | Dim 1 | Dim 2 |
|---|---|---|
| Rango de área | 0,870 | 0,204 |
| Rango de precio | 0,756 | 0,154 |
| Rango de habitaciones | 0,535 | 0,299 |
| Tipo de vivienda | 0,387 | 0,304 |
| Estrato | 0,325 | 0,581 |
| Zona | 0,070 | 0,524 |
La Dimensión 1 es física y económica: la gobiernan el área y el precio. La Dimensión 2 es socio-territorial: la gobiernan la zona y el estrato. El contraste decisivo está en la fila de la zona: η² = 0,070 sobre el eje físico frente a 0,524 sobre el socio-territorial.
Dicho en términos de negocio: saber en qué zona está una vivienda informa sobre su estrato, pero casi nada sobre su tamaño o su precio. Las dos lógicas del mercado son ortogonales.
El mapa ordena las modalidades de precio, área y habitaciones a lo largo del eje horizontal en secuencia monótona, de “bajo/chica” a la izquierda hasta “alto/grande” a la derecha, lo que confirma que la Dimensión 1 es un gradiente de magnitud. En el eje vertical se separan Zona Oriente y el estrato 3 en el extremo superior de Zona Oeste y el estrato 6 en el inferior.
Mapa interactivo: los controles de la esquina superior derecha permiten aislar cada segmento; al hacer clic sobre una vivienda se despliegan sus atributos.
La proyección espacial confirma la estructura detectada analíticamente. El segmento de alto standing se concentra en el corredor occidental y sur; el segmento de metro cuadrado barato aparece disperso hacia el oriente y el nororiente, en las zonas que el análisis de correspondencias identificó como especializadas en estrato 3.
Un mapa de calor sobre los puntos individuales resultaría engañoso: acumula intensidad allí donde hay muchos avisos, de modo que mostraría la densidad de la oferta y no el nivel de precios. Zona Sur, con más de la mitad del volumen, dominaría la imagen. Se agrega por tanto la información a nivel de barrio.
Cada círculo es un barrio con 30 avisos o más. El área representa el volumen de oferta y el color el precio mediano por metro cuadrado. Al pasar el cursor se muestra el valor; al hacer clic, el perfil completo del barrio.
| Barrios en los extremos del valor unitario | |||||
| Vista tabular del mapa anterior, sobre los 55 barrios con 30 avisos o más | |||||
| Barrio | Avisos | Precio mediano (M) | Área mediana (m²) | Precio/m² | Estrato modal |
|---|---|---|---|---|---|
| Mayor precio por m² | |||||
| santa teresita | 261 | 750 | 194 | 4,08 | 6 |
| normandía | 153 | 621 | 166 | 3,96 | 6 |
| cristales | 83 | 450 | 120 | 3,88 | 6 |
| arboledas | 38 | 630 | 191 | 3,85 | 6 |
| pance | 406 | 775 | 197 | 3,83 | 6 |
| Menor precio por m² | |||||
| vipasa | 31 | 380 | 265 | 1,44 | 4 |
| el bosque | 49 | 350 | 215 | 1,66 | 5 |
| villa del prado | 50 | 158 | 85 | 1,69 | 3 |
| san vicente | 48 | 455 | 297 | 1,73 | 5 |
| ciudad 2000 | 95 | 325 | 170 | 1,82 | 4 |
La tabla precede a cualquier lectura cromática: el mapa comunica el patrón, y los valores concretos quedan disponibles en forma numérica.
La comparación entre ambos gráficos corrige una intuición frecuente. Las medianas por zona recorren un rango más amplio (de 1,31 a 3,71 M/m²) que las medianas por segmento (de 1,46 a 2,95). Para cuantificarlo se calcula la proporción de varianza del precio por metro cuadrado que explica cada factor.
El resultado separa dos preguntas que suelen confundirse:
Esto no contradice el resultado del ACM, lo precisa. Allí la zona apenas se relacionaba con el eje físico-económico, que mide tamaño y precio absoluto; aquí se confirma justamente eso (η² = 0,116 sobre el precio total). El valor unitario es una dimensión distinta, y en ella la geografía manda.
Sobre la estructura del mercado (ACP). Cinco variables se reducen a dos dimensiones que retienen el 81,83 % de la información. La primera, con el 63,43 %, es un factor de tamaño general en el que todas las variables cargan positivamente. La segunda, con el 18,39 %, opone habitaciones a parqueaderos y precio, y constituye un eje de gama independiente del tamaño.
Sobre el valor unitario. El precio por metro cuadrado correlaciona 0,021 con el eje de tamaño y −0,564 con el eje de gama: el tamaño de una vivienda no predice su valor unitario. Lo que sí lo predice es la localización. El barrio explica el 45,8 % de su varianza y el estrato el 32,2 %, frente al 13,0 % del segmento. Precio total y precio unitario responden por tanto a lógicas distintas: el primero a la estructura del producto, el segundo a la geografía.
Sobre la segmentación (conglomerados). El mercado se organiza en cuatro segmentos que explican el 75,4 % de la inercia total. El apartamento estándar representa la mitad de la oferta; el alto standing, una décima parte. Entre ellos, un segmento del 9,1 % concentra casas grandes de estrato 3 y 4 con un precio por metro cuadrado un 45 % inferior al del mercado.
Sobre la geografía de la oferta (correspondencias). La asociación entre zona y estrato es intensa (V de Cramér = 0,392) y se resume en dos dimensiones que retienen el 97,59 % de la inercia. El mercado está segregado en un eje oriente–occidente: Zona Oriente es estrato 3 en el 96,8 % de su oferta y Zona Oeste es estrato 6 en el 64,6 %. Zona Sur, con el 57,0 % del volumen, es la única zona con perfil equilibrado.
Sobre la independencia de las lógicas de mercado (ACM). Con la corrección de Benzécri, dos dimensiones retienen el 87,65 % de la inercia. La primera responde a área y precio (η² de 0,870 y 0,756); la segunda a zona y estrato (0,524 y 0,581). La zona apenas se relaciona con el eje físico-económico (η² = 0,070). La localización determina el entorno socioeconómico, no el producto inmobiliario.
1. Constituir una línea de adquisición sobre el segmento S2. Es la recomendación de mayor impacto potencial. Las casas grandes de estrato 3 y 4 se ofertan a 1,46 millones por m² frente a 2,67 del apartamento estándar. Con 300 m² de mediana, estos inmuebles admiten subdivisión, adecuación para renta por habitaciones o reconversión a uso mixto. Se sugiere iniciar con un piloto acotado a Zona Oriente y Zona Sur, donde el segmento tiene mayor densidad, antes de escalar.
2. Valorar con dos predictores, no con uno. El análisis muestra que precio total y precio unitario obedecen a factores distintos: el segmento explica el 69,9 % de la varianza del precio total pero solo el 13,0 % de la del precio por metro cuadrado, donde el barrio (45,8 %) y el estrato (32,2 %) dominan. Un modelo de tasación construido sobre un solo eje, sea la ubicación o sea la tipología, queda ciego a la mitad del fenómeno. La recomendación es incorporar ambos: la variable de segmentación desarrollada en este informe para estimar el nivel de precio, y el barrio o el estrato para calibrar el valor por metro cuadrado.
3. Diferenciar la estrategia comercial por zona según su perfil. Zona Sur, con el 57,0 % del volumen y un perfil próximo al promedio, admite un portafolio diversificado. Zona Oeste, con el 64,6 % de su oferta en estrato 6, requiere una propuesta especializada en alto standing. Zona Oriente y Zona Centro, con más del 84 % en estrato 3, son el territorio natural de la línea recomendada en el punto 1.
4. Revisar la calidad del dato de origen antes de escalar la analítica. El 21,5 % de los barrios aparece asignado a más de una zona y el 31,7 % de los registros carece del dato de piso. Consolidar un maestro de barrios georreferenciado es un prerrequisito para cualquier modelo predictivo confiable.
5. Ampliar la cobertura a estratos 1 y 2. La base actual no contiene registros de estos estratos, lo que deja fuera del análisis un tramo relevante del mercado urbano. Cualquier decisión sobre vivienda de interés social requiere una fuente de datos complementaria.
Se contrasta la solución factorial adoptada, con imputación en cero, contra la que resultaría de eliminar por lista los registros sin dato.
| Varianza explicada bajo ambos tratamientos | |||
| n con imputación: 8.243 · n solo observados: 6.688 | |||
| Dimensión | % con imputación | % solo observados | Diferencia (pp) |
|---|---|---|---|
| Dim 1 | 63,43 | 65,55 | −2,11 |
| Dim 2 | 18,39 | 17,04 | 1,36 |
| Dim 3 | 8,14 | 7,23 | 0,91 |
| Dim 4 | 6,28 | 6,40 | −0,12 |
| Dim 5 | 3,76 | 3,78 | −0,03 |
| Cargas factoriales bajo ambos tratamientos | ||||
| Correlación entre configuraciones — Dim 1: 0,9649 · Dim 2: 0,99 | ||||
| Variable | Dim1 imputado | Dim1 observado | Dim2 imputado | Dim2 observado |
|---|---|---|---|---|
| Precio | 0,848 | 0,841 | −0,340 | −0,387 |
| Área | 0,866 | 0,871 | 0,105 | 0,055 |
| Parqueaderos | 0,722 | 0,788 | −0,514 | −0,393 |
| Baños | 0,885 | 0,882 | 0,132 | 0,139 |
| Habitaciones | 0,631 | 0,642 | 0,715 | 0,724 |
Conclusión. Las configuraciones de variables
correlacionan 0,965 en la primera dimensión y 0,990 en la segunda. La
varianza de la Dimensión 1 varía en 2,1 puntos porcentuales y la única
carga que se desplaza de forma apreciable es la del propio
parqueaderos, como era esperable al ampliar su rango.
La estructura factorial es robusta a la decisión de
imputación, de modo que la opción adoptada conserva 1.555
observaciones del extremo bajo del mercado sin alterar los
resultados.
La partición de k-medias se contrasta contra un método de naturaleza distinta: clasificación jerárquica aglomerativa con criterio de Ward, sobre una muestra aleatoria de 1.500 viviendas.
| Tabla de contingencia entre ambas particiones | ||||
| Concordancia máxima: 1333 de 1500 casos (88,9 %) | ||||
| Jerárquico |
k-medias
|
|||
|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |
| 1 | 739 | 0 | 85 | 0 |
| 2 | 5 | 111 | 5 | 18 |
| 3 | 6 | 24 | 354 | 0 |
| 4 | 0 | 0 | 24 | 129 |
Dos algoritmos con lógicas distintas (uno aglomerativo por minimización de varianza, otro de partición por optimización de centroides) asignan el 88,9 % de las viviendas al mismo grupo. La estructura de cuatro segmentos no es un artefacto del método elegido.
Adicionalmente, los saltos relativos entre alturas de fusión consecutivas del dendrograma presentan un máximo local en k = 4, coherente con el criterio del codo aplicado sobre la inercia intra-grupo.
| Estadísticos descriptivos de las variables cuantitativas | |||||||||
| Base depurada: 8.243 registros en todas las variables | |||||||||
| Variable | Media | Desv. est. | Mín | P25 | Mediana | P75 | P95 | Máx | Asimetría |
|---|---|---|---|---|---|---|---|---|---|
| Baños | 3,13 | 1,41 | 1,00 | 2,00 | 3,00 | 4,00 | 6,00 | 10,00 | 0,98 |
| Habitaciones | 3,63 | 1,43 | 1,00 | 3,00 | 3,00 | 4,00 | 7,00 | 10,00 | 1,82 |
| Parqueaderos | 1,49 | 1,24 | 0,00 | 1,00 | 1,00 | 2,00 | 4,00 | 10,00 | 1,63 |
| Precio (M) | 433,27 | 328,93 | 58,00 | 220,00 | 330,00 | 540,00 | 1.200,00 | 1.999,00 | 1,85 |
| Precio/m² | 2,73 | 1,08 | 0,15 | 1,92 | 2,65 | 3,38 | 4,63 | 9,47 | 0,68 |
| Área (m²) | 174,04 | 142,32 | 30,00 | 80,00 | 122,00 | 227,00 | 450,00 | 1.745,00 | 2,73 |
| Distribución conjunta de segmento y zona | |||||
| Frecuencias absolutas | |||||
| Segmento |
Zona
|
||||
|---|---|---|---|---|---|
| Zona Centro | Zona Norte | Zona Oeste | Zona Oriente | Zona Sur | |
| S1 · Apartamento estándar | 60 | 1.159 | 309 | 180 | 2.443 |
| S2 · Metro cuadrado barato | 38 | 176 | 45 | 135 | 357 |
| S3 · Media-alta consolidada | 21 | 470 | 594 | 27 | 1.376 |
| S4 · Alto standing | 2 | 83 | 240 | 3 | 525 |
La reproducibilidad exacta de los resultados requiere la semilla
set.seed(2026) declarada al inicio del documento y las
versiones de paquetes que se listan a continuación.
| Entorno de cómputo | ||
| R version 4.6.1 (2026-06-24) · Linux · semilla set.seed(2026) | ||
| Paquete | Versión | Papel en el análisis |
|---|---|---|
| FactoMineR | 2.16 | Componentes principales, correspondencias simples y múltiples |
| factoextra | 2.2.0 | Extracción y visualización de resultados factoriales |
| cluster | 2.1.8.3 | Silueta y validación de conglomerados |
| ggplot2 | 4.0.3 | Gramática de gráficos |
| patchwork | 1.3.2 | Composición de gráficos múltiples |
| ggrepel | 0.9.8 | Etiquetado sin superposición |
| ggcorrplot | 0.3.0 | Matriz de correlaciones |
| dplyr | 1.2.1 | Manipulación de datos |
| tidyr | 1.3.2 | Reestructuración de datos |
| gt | 1.3.0 | Tablas del informe |
| leaflet | 2.2.3 | Cartografía interactiva |
| rmarkdown | 2.31 | Generación del documento |
| knitr | 1.51 | Motor de ejecución de código |
vivienda. Datos obtenidos de OLX mediante
procedimiento de web scraping.