# Instalación automática de librerias
paquetes <- c("dplyr", "tidyr", "ggplot2", "scales", "knitr", "kableExtra",
"FactoMineR", "factoextra", "cluster", "corrplot", "gridExtra",
"naniar", "mice")
faltantes <- paquetes[!paquetes %in% rownames(installed.packages())]
if (length(faltantes) > 0) install.packages(faltantes, dependencies = TRUE)
suppressPackageStartupMessages({
library(dplyr); library(tidyr); library(ggplot2)
library(scales); library(knitr); library(kableExtra)
library(FactoMineR); library(factoextra); library(cluster)
library(corrplot); library(gridExtra)
library(naniar); library(mice)
})
set.seed(2026) # Semilla# visual único para todo el informe
# Paleta de colores
pal_cat <- c("#2a78d6", "#eb6834", "#1baf7a", "#eda100",
"#e87ba4", "#008300", "#4a3aa7", "#e34948")
pal_seq <- c("#cde2fb", "#9ec5f4", "#6da7ec", "#3987e5", "#256abf", "#184f95", "#0d366b")
pal_div <- c("#2a78d6", "#f0efec", "#e34948")
tema_informe <- theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 13, colour = "#0b0b0b"),
plot.subtitle = element_text(size = 10.5, colour = "#52514e", margin = margin(b = 8)),
plot.caption = element_text(size = 8.5, colour = "#7a7975", hjust = 0),
axis.title = element_text(size = 10, colour = "#52514e"),
axis.text = element_text(size = 9.5, colour = "#52514e"),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(colour = "#e8e7e3", linewidth = 0.35),
legend.position = "top",
legend.title = element_text(size = 9.5, colour = "#52514e"),
legend.text = element_text(size = 9.5),
strip.text = element_text(face = "bold", size = 10, colour = "#0b0b0b")
)
theme_set(tema_informe)
# Título de figuras
titulo_fig <- function(txt) grid::textGrob(txt, x = 0.01, hjust = 0,
gp = grid::gpar(fontsize = 13, fontface = "bold", col = "#0b0b0b"))
# Función de tablas
tabla <- function(x, cap = NULL, ...) {
kable(x, caption = cap, ...) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, position = "center", font_size = 13)
}## [1] 8322 13
La base contiene 8.322 registros. El estudio trabaja con once variables las cuales se describen en la Tabla 1.
viv0 <- viv0 %>%
select(id, zona, piso, estrato, preciom, areaconst,
parqueaderos, banios, habitaciones, tipo, barrio)
dim(viv0)## [1] 8322 11
En total el dataset posee 10 variables, de las cuales 5 son cualitativas y 5 cuantitativas mas una columna de identificacion (ID), estas se pueden apreciar en la Tabla 1.
| Variable | Descripción | Naturaleza | Tipo de variable | Escala de medición |
|---|---|---|---|---|
| id | Código único del anuncio | Identificador | — | — |
| zona | Zona de la ciudad (Norte, Sur, Oriente, Oeste, Centro) | Cualitativa | Nominal | Nominal |
| barrio | Barrio de ubicación (436 categorías en bruto; 388 tras normalizar) | Cualitativa | Nominal | Nominal |
| tipo | Casa o Apartamento | Cualitativa | Nominal | Nominal |
| estrato | Estrato socioeconómico (3, 4, 5 o 6) | Cualitativa | Ordinal | Ordinal |
| piso | Piso en que se ubica el inmueble (01 a 12) | Cualitativa | Ordinal | Ordinal |
| preciom | Precio de venta en millones de pesos colombianos | Cuantitativa | Continua | Razón |
| areaconst | Área construida en metros cuadrados | Cuantitativa | Continua | Razón |
| parqueaderos | Número de parqueaderos | Cuantitativa | Discreta | Razón |
| banios | Número de baños | Cuantitativa | Discreta | Razón |
| habitaciones | Número de habitaciones | Cuantitativa | Discreta | Razón |
El estrato es una variable cualitativa, no cuantitativa, aunque se escriba con números es por esto que en el código se declara como factor y no como numérico:
La variable de piso también es cualitativa ordinal por lo que se trata como una variable categórica
# Minusculas y espacios unificados
normaliza_texto <- function(x) trimws(gsub("[[:space:]]+", " ", tolower(x)))
# En barrio se añade la eliminación del artículo determinado inicial
normaliza_barrio <- function(x) sub("^(el|la|los|las) ", "", normaliza_texto(x))
# zona y tipo: se devuelven a su forma de presentación (mayúscula inicial) para que las etiquetas de tablas y gráficos se lean bien
capitaliza <- function(x) gsub("\\b([a-záéíóúñ])", "\\U\\1", x, perl = TRUE)
viv0 <- viv0 %>%
mutate(zona = capitaliza(normaliza_texto(zona)),
tipo = capitaliza(normaliza_texto(tipo)),
barrio = normaliza_barrio(barrio))
c(barrios_antes = 436, barrios_despues = n_distinct(viv0$barrio[!is.na(viv0$barrio)]))## barrios_antes barrios_despues
## 436 388
En esta etapa de normalizan las etiquetas de texto para que R pueda realizar una lectura adecuada de los datos presentes, ya que para R es diferente Lili a lili, es necesario realizar este paso para garantizar la fiabilidad de el analisis correspondiente
Cada fila corresponde a un anuncio independiente, por lo que la informacion presente en cada uno no deberia repetirse.
## Registros completamente vacíos: 3
## Filas duplicadas exactas: 1
Se identificaron 3 registros completamente vacíos y 1 fila duplicada que se eliminan conservando un registro original de cada uno.
## Inmuebles con 0 baños: 45
## Inmuebles con 0 habitaciones: 66
## Áreas menores a 20 m²: 0
## Precios no positivos: 0
Se encontraron 45 inmuebles con 0 baños y 66 con 0 habitaciones ya que una vivienda en venta no puede carecer de ninguno de los dos se tratan como NA y se retomaran en la sección 2.3.
viv <- viv0 %>%
filter(!is.na(id)) %>% # elimina los 3 registros vacíos
distinct() %>% # elimina el duplicado exacto
mutate(
banios = ifelse(banios == 0, NA, banios),
habitaciones = ifelse(habitaciones == 0, NA, habitaciones)
)
c(registros = nrow(viv), barrios = n_distinct(viv$barrio))## registros barrios
## 8319 388
A continuacion se presentan los datos atipicos encontrados en el dataset ademas de diferentes meddicas estadisticas calculadas en la Tabla 2, por otra parte en la figura 1 es posible observar el porcentaje de datos atipicos por variable.
cuant <- c("preciom", "areaconst", "parqueaderos", "banios", "habitaciones")
resumen_atipicos <- do.call(rbind, lapply(cuant, function(nm) {
x <- viv[[nm]]
q <- quantile(x, c(.25, .75), na.rm = TRUE)
iqr <- q[2] - q[1]
li <- q[1] - 1.5 * iqr
ls <- q[2] + 1.5 * iqr
n <- sum(x < li | x > ls, na.rm = TRUE)
data.frame(Variable = nm,
Media = round(mean(x, na.rm = TRUE), 2), Mediana = median(x, na.rm = TRUE),
Mín = min(x, na.rm = TRUE), Q1 = unname(q[1]), Q3 = unname(q[2]),
Máx = max(x, na.rm = TRUE),
"Límite inf." = round(li, 1), "Límite sup." = round(ls, 1),
"Atípicos" = n, "% atípicos" = round(100 * n / sum(!is.na(x)), 2),
check.names = FALSE, row.names = NULL)
}))| Variable | Media | Mediana | Mín | Q1 | Q3 | Máx | Límite inf. | Límite sup. | Atípicos | % atípicos |
|---|---|---|---|---|---|---|---|---|---|---|
| preciom | 433.90 | 330 | 58 | 220 | 540 | 1999 | -260.0 | 1020.0 | 552 | 6.64 |
| areaconst | 174.93 | 123 | 30 | 80 | 229 | 1745 | -143.5 | 452.5 | 382 | 4.59 |
| parqueaderos | 1.84 | 2 | 1 | 1 | 2 | 10 | -0.5 | 3.5 | 567 | 8.44 |
| banios | 3.13 | 3 | 1 | 2 | 4 | 10 | -1.0 | 7.0 | 72 | 0.87 |
| habitaciones | 3.63 | 3 | 1 | 3 | 4 | 10 | 1.5 | 5.5 | 822 | 9.96 |
Tomando encuenta que en esta seccion se toma el dataset en general, es necesario realizar una division segun los estratos ya que se espera que las variables economicas les correspondan valores mas altos a medida que sube el estrato, sin ser datos atipicos.
lim_iqr <- function(x) {
q <- quantile(x, c(.25, .75), na.rm = TRUE); i <- q[2] - q[1]
x < q[1] - 1.5 * i | x > q[2] + 1.5 * i
}
comparacion <- do.call(rbind, lapply(cuant, function(nm) {
x <- viv[[nm]]
g <- sum(lim_iqr(x), na.rm = TRUE) # criterio global
e <- sum(unlist(lapply(split(x, viv$estrato), lim_iqr)), na.rm = TRUE) # por estrato
n <- sum(!is.na(x))
data.frame(Variable = nm,
"Atípicos (global)" = g, "% global" = round(100 * g / n, 2),
"Atípicos (por estrato)" = e, "% por estrato" = round(100 * e / n, 2),
"Variación" = sprintf("%+.0f %%", 100 * (e / g - 1)),
check.names = FALSE, row.names = NULL)
}))| Variable | Atípicos (global) | % global | Atípicos (por estrato) | % por estrato | Variación |
|---|---|---|---|---|---|
| preciom | 552 | 6.64 | 340 | 4.09 | -38 % |
| areaconst | 382 | 4.59 | 496 | 5.96 | +30 % |
| parqueaderos | 567 | 8.44 | 795 | 11.84 | +40 % |
| banios | 72 | 0.87 | 306 | 3.70 | +325 % |
| habitaciones | 822 | 9.96 | 572 | 6.93 | -30 % |
El resultado matiza la intuición de partida y merece leerse con cuidado, porque el efecto no va en la misma dirección para todas las variables:
La Figura 3 muestra que el umbral global de precio se sitúa en 1.000 M y es único para toda la base, mientras que el condicionado va de 500 M en estrato 3 a $1.700 M en estrato 6.
Tomando encuenta la informacion obtenida en los pasos anteriores se opto por realizar el calculo del percentil 99 dentro de cada estrato y así cada inmueble se le recorta contra el techo de su propio segmento y se evita el doble sesgo que acaba de apreciarse, dando como resultado los rangos de precios presentados en la Tabla 4.
# Percentil 99 calculado dentro de cada estrato
cap_99_estrato <- function(x, grupo) {
ave(x, grupo, FUN = function(z) {
s <- quantile(z, 0.99, na.rm = TRUE); ifelse(z > s, s, z)
})
}
viv_antes <- viv # copia para comparar
viv$preciom <- cap_99_estrato(viv$preciom, viv$estrato)
viv$areaconst <- cap_99_estrato(viv$areaconst, viv$estrato)| Estrato | n | P99 precio (M) | P99 área (m²) | Precios recortados | Áreas recortadas |
|---|---|---|---|---|---|
| 3 | 1453 | 674 | 514.8 | 15 | 15 |
| 4 | 2129 | 800 | 507.8 | 20 | 22 |
| 5 | 2750 | 1400 | 685.3 | 22 | 28 |
| 6 | 1987 | 1850 | 934.2 | 13 | 20 |
El percentil 99 del precio va de 674 M en el estrato 3 a 1.850 M en el estrato 6, frente al valor único de 1.650 M que habría impuesto el cálculo global, ademas de afectar los diferentes calculos de medida de tendencia central, los cuales se pueden observar en las Tablas 4 y 5 justificando asi este procedimiento
| Variable | Media antes | Media después | Mediana antes | Mediana después | SD antes | SD después | Asimetría antes | Asimetría después | Máx antes | Máx después |
|---|---|---|---|---|---|---|---|---|---|---|
| preciom | 433.9 | 431.8 | 330 | 330 | 328.7 | 323.4 | 1.85 | 1.82 | 1999 | 1850.0 |
| areaconst | 174.9 | 173.1 | 123 | 123 | 143.0 | 133.2 | 2.69 | 1.96 | 1745 | 934.2 |
La mediana de ambas variables no cambia lo que confirma que la intervención no desplaza el centro de la distribución. Lo que sí cambia es la dispersión y la forma: la desviación estándar del área baja de lijeramente, representando asi un cambio minimio en el comportamiento de los datos tal como se puede apreciar en la FIgura 4.
A continuacion se realizo la busqueda de valores faltantes en el dataset cuyos resultados se pueden apreciar tanto en la Tabla 6 como en la Figura 5 donde se inlcuye el porcentaje de los mismos, por otra parte en la Figura 6 se muestran las combinaciones de datos faltantes presentes en el dataset.
| Variable | Número de datos NA | Porcentaje de NA (%) |
|---|---|---|
| piso | 2635 | 31.67 |
| parqueaderos | 1602 | 19.26 |
| habitaciones | 66 | 0.79 |
| banios | 45 | 0.54 |
| id | 0 | 0.00 |
| zona | 0 | 0.00 |
| estrato | 0 | 0.00 |
| preciom | 0 | 0.00 |
| areaconst | 0 | 0.00 |
| tipo | 0 | 0.00 |
| barrio | 0 | 0.00 |
En total se identificaron 4.348 celdas faltantes repartidas en cuatro variables. El 80,4 % de los registros está completo en las variables que efectivamente alimentan el análisis realizado a continuacion.
Piso (31,67 %): Falta en 1.254 de las 3.219 casas, donde la variable no aplica ya que una casa no tiene “piso” en el sentido en que lo tiene un apartamento, es por esto que se conserva como variable descriptiva pero se excluye de todos los análisis multivariados y no se imputa.
Parqueaderos (19,26 %): Este presenta un patrón muy marcado por estrat que se evidencia en la tabla 7.
Banios` (0,54 %) y habitaciones (0,79 %): Provienen íntegramente de la recodificación de los ceros imposibles detectados en la sección 2.1. Su volumen es mínimo y no compromete la integridad del análisis.
| % con dato | % sin dato | |
|---|---|---|
| 3 | 47.1 | 52.9 |
| 4 | 77.1 | 22.9 |
| 5 | 91.7 | 8.3 |
| 6 | 94.1 | 5.9 |
Para evaluar formalmente si los datos faltantes se distribuyen de manera completamente aleatoria se aplicó la prueba de Little sobre las variables cuantitativas. Su hipótesis nula establece que los datos faltantes son MCAR (Missing Completely At Random), la alternativa, que no lo son. Dado el tamaño de la base (8.319 registros) se fijó un nivel de significancia de α = 0,05.
El valor p obtenido es prácticamente cero (\(\chi^2 = 743{,}12\) con 23 grados de libertad, 8 patrones de ausencia distintos), muy inferior a α = 0,05, por lo que se rechaza la hipótesis nula los datos faltantes no se distribuyen de forma completamente aleatoria, es decir, no son MCAR.
Los gráficos presentes en la Figura 7 muestran desviaciones sistemáticas en ambos extremos y las densidades confirman distribuciones discretas y asimétricas a la derecha en parqueaderos y en habitaciones), lo que compromete parcialmente la fiabilidad del test de Little, el cual supone normalidad multivariada, ademas descarta el uso de la media como método de imputación.
Para determinar si la probabilidad de ausencia depende de variables observadas (lo que definiría un mecanismo MAR) se construyó, para cada variable con datos faltantes,un indicador binario que vale 1 cuando el dato está ausente y 0 cuando está presente y se ajustó un modelo de regresión logística con variables restantes como explicativas.
viv$parq_NA <- as.integer(is.na(viv$parqueaderos))
mod_parq <- glm(parq_NA ~ preciom + areaconst + estrato + I(tipo == "Casa"),
family = binomial, data = viv)
summary(mod_parq)##
## Call:
## glm(formula = parq_NA ~ preciom + areaconst + estrato + I(tipo ==
## "Casa"), family = binomial, data = viv)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 2.971006 0.167182 17.77 <0.0000000000000002 ***
## preciom -0.000707 0.000263 -2.69 0.0071 **
## areaconst 0.000444 0.000457 0.97 0.3319
## estrato -0.996463 0.045945 -21.69 <0.0000000000000002 ***
## I(tipo == "Casa")TRUE 0.153859 0.082319 1.87 0.0616 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 8151.5 on 8318 degrees of freedom
## Residual deviance: 6797.8 on 8314 degrees of freedom
## AIC: 6808
##
## Number of Fisher Scoring iterations: 5
La variable estrato resulta altamente significativa, cada escalón de estrato reduce en un 64 % la probabilidad de que el dato de parqueaderos falte. La Tabla 7 lo evidencia, el 52,9 % de los inmuebles de estrato 3 no reporta el dato, frente a solo el 5,9 % en estrato 6.
viv$ban_NA <- as.integer(is.na(viv$banios))
viv$hab_NA <- as.integer(is.na(viv$habitaciones))
summary(glm(ban_NA ~ preciom + areaconst + estrato, family = binomial, data = viv))$coefficients## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -3.6785362 0.7042301 -5.223 0.0000001756
## preciom 0.0002094 0.0007322 0.286 0.7748547370
## areaconst 0.0046382 0.0010865 4.269 0.0000196246
## estrato -0.5962695 0.1925628 -3.096 0.0019582400
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.5155158 0.5821913 -4.3208 0.000015548
## preciom 0.0004233 0.0006490 0.6522 0.514246895
## areaconst 0.0042016 0.0009726 4.3197 0.000015623
## estrato -0.7769348 0.1645041 -4.7229 0.000002325
En banios y habitaciones resultan significativas areaconst en ambos casos y estrato, la probabilidad de ausencia depende de variables observadas, de modo que el patrón es consistente con un mecanismo MAR (Missing At Random) y no con un mecanismo completamente aleatorio.
| Variable | % NA | Evidencia | Mecanismo | Tratamiento |
|---|---|---|---|---|
| piso | 31.67 | Falta en 1.254 de 3.219 casas: la variable no aplica al tipo de inmueble | Estructural (no aplica) | No se imputa; se excluye del análisis multivariado |
| parqueaderos | 19.26 | estrato altamente significativo (OR = 0,36 por escalón); el valor 0 no existe en la base | Estructural / MNAR | Imputación determinística con 0 |
| banios | 0.54 | areaconst y estrato significativos; procede de ceros imposibles | MAR | Imputación múltiple (mice, PMM) |
| habitaciones | 0.79 | areaconst y estrato significativos; procede de ceros imposibles | MAR | Imputación múltiple (mice, PMM) |
En la Tabla 8 es posible observar un resumen de los mecanismos de datos faltantes encontrados en el dataset segun cada variable.
Para banios y habitaciones se aplica una imputación múltiple por encadenamiento (mice) con el método PMM (Predictive Mean Matching), elegido porque no supone normalidad y porque solo puede devolver valores que ya existen en los datos observados, lo que garantiza imputaciones enteras y plausibles para variables de conteo. Se generan \(m = 5\) imputaciones con 10 iteraciones esto se puede apreciar de manera resumida en la Tabla 9.
bloque <- viv %>% select(preciom, areaconst, parqueaderos, banios, habitaciones, estrato)
imp <- mice(bloque, m = 5, maxit = 10, method = "pmm", printFlag = FALSE, seed = 2026)
completo <- complete(imp, 1)| Variable | Método de imputación | |
|---|---|---|
| preciom | preciom | — (sin faltantes) |
| areaconst | areaconst | — (sin faltantes) |
| parqueaderos | parqueaderos | pmm |
| banios | banios | pmm |
| habitaciones | habitaciones | pmm |
| estrato | estrato | — (sin faltantes) |
En la Figura 9 se muestran las líneas que oscilan entre sí, cruzándose sin una tendencia creciente o decreciente clara alrededor de un rango estable, esto permite afirmar que la imputacion no afecto negativamente el comportamiento de los datos en general.
Por otra parte en la Figura 10 la línea azul representa los datos originales observados y las líneas rosadas cada una de las cinco imputaciones, en esta figura se destaca que las imputaciones realizadas concuerdan con el comportamiento de los datos previos, es decir, los datos se suavizaron luego de la imputacion realizada
La Figura 11 se realizó sobre habitaciones, la variable con mayor número de valores imputados, Los valores imputados (puntos rojos) se mezclan bien con los valores observados (puntos azules), sin concentrarse en zonas anómalas del rango, lo que indica que la imputación es coherente con la estructura de los datos.
viv$banios <- completo$banios
viv$habitaciones <- completo$habitaciones
viv$parqueaderos <- ifelse(is.na(viv$parqueaderos), 0, viv$parqueaderos) # ausencia estructural
sum(is.na(viv[, cuant])) # 0 faltantes en las variables de análisis## [1] 0
Repecto a las variables cualitativas presentes en el dataset, ninguna de las cinco variables cualitativas requirió imputación:
viv <- viv %>%
select(-parq_NA, -ban_NA, -hab_NA) %>%
mutate(
precio_m2 = preciom * 1e6 / areaconst,
zona = factor(zona),
tipo = factor(tipo),
estrato = factor(estrato, levels = 3:6, ordered = TRUE),
rango_precio = cut(preciom, breaks = c(0, 200, 350, 600, Inf),
labels = c("Económico", "Medio", "Alto", "Premium")),
rango_area = cut(areaconst, breaks = c(0, 80, 150, 300, Inf),
labels = c("Pequeña", "Mediana", "Grande", "Muy grande"))
)
c(registros = nrow(viv), variables = ncol(viv))## registros variables
## 8319 14
Los cortes de rango_precio se fijaron en los cuartiles redondeados de la distribución y los de rango_area en umbrales de mercado (80, 150 y 300 m2), de modo que las categorías sean interpretables por un corredor y no solo estadísticamente balanceadas.
| Variable | Mínimo | Máximo | Media | Desv. estándar | Q1 | Mediana | Q3 | Coef. variación (%) | Asimetría | Moda |
|---|---|---|---|---|---|---|---|---|---|---|
| preciom | 58 | 1850.0 | 431.79 | 323.44 | 220 | 330 | 540 | 74.9 | 1.82 | 350 |
| areaconst | 30 | 934.2 | 173.07 | 133.18 | 80 | 123 | 229 | 77.0 | 1.96 | 60 |
| parqueaderos | 0 | 10.0 | 1.48 | 1.24 | 1 | 1 | 2 | 83.9 | 1.65 | 1 |
| banios | 1 | 10.0 | 3.13 | 1.41 | 2 | 3 | 4 | 45.2 | 0.98 | 2 |
| habitaciones | 1 | 10.0 | 3.64 | 1.44 | 3 | 3 | 4 | 39.4 | 1.82 | 3 |
| precio_m2 | 280992 | 9468085.1 | 2719974.33 | 1077400.62 | 1915635 | 2637363 | 3376623 | 39.6 | 0.69 | 2500000 |
Las medidas de la Tabla 10 solo tienen sentido para el bloque cuantitativo. Para las variables cualitativas la descripción adecuada es la distribución de frecuencias, con la moda como medida de posición, tal como se aprecia en la figura 11 y tabla 11.
| Variable | Categorías | Moda | Frec. de la moda | % de la moda | Categoría menos frecuente | Frec. mínima |
|---|---|---|---|---|---|---|
| zona | 5 | Zona Sur | 4726 | 56.8 | Zona Centro | 124 |
| tipo | 2 | Apartamento | 5100 | 61.3 | Casa | 3219 |
| estrato | 4 | 5 | 2750 | 33.1 | 3 | 1453 |
| barrio | 388 | valle del lili | 1009 | 12.1 | 3 de julio | 1 |
La base final contiene 8.319 registros sin valores faltantes en las variables de análisis. Sobre esta se desarrolla el resto del informe.
La asimetría positiva que persiste tras el tratamiento (1,82 en preciom y 1,96 en areaconst) es el hecho estadístico más relevante de la Tabla 10: la media (432 M) supera a la mediana 330 M) en un 31 %, todo el informe usa la mediana como medida de posición, por otra parte destacan los coheficientes de variacion de: preciom y areaconst, los cuales superan el 74 %, mientrasque precio_m2 se queda en 39,6 % demostrando mayor estabilidad y por eso resulta un mejor indicador de gestión.
Es posible observar en las figuras 13 y 14 que La Zona Sur concentra el 56,8 % de toda la oferta y la Zona Norte el 23,1 %, entre las dos suman cuatro de cada cinco anuncios, por otra parte, La Zona Centro (1,5 %) y la Zona Oriente (4,2 %) están estructuralmente subrepresentadas en el mercado formal. En cuanto a los apartamentos, estos predominan (61,3 %), pero la proporción se invierte en los estratos bajos.
El precio por metro cuadrado crece de forma monótona pero no lineal, el salto de estrato 3 a 4 es de +47 %, mientras que de 4 a 5 es de solo +13 % y de 5 a 6 de +30 %, es decir, el estrato 4 y el 5 comparten un rango de valorización por metro muy parecido, lo que los separa es el tamaño del inmueble, no su precio unitario, este comportamiento es posible observarlo en la Figura 15.
En la figura 16 se puede observar como las cuatro rectas son aproximadamente paralelas y están desplazadas verticalmente. Eso significa que el estrato opera como un factor multiplicativo sobre el precio, es decir un mismo metro adicional se paga proporcionalmente igual en todos los estratos, pero partiendo de bases distintas.
| Par de variables | r | Lectura |
|---|---|---|
| precio – área construida | 0.711 | El área es el mejor predictor individual del precio total |
| área – baños | 0.703 | Consistencia interna del tamaño del inmueble |
| precio – baños | 0.684 | El número de baños opera como proxy del estándar de acabados |
| precio – parqueaderos | 0.646 | Relación fuerte: el parqueadero es un atributo de precio, no de tamaño |
| precio – estrato | 0.623 | El estrato aporta casi tanto como los atributos físicos |
| baños – habitaciones | 0.594 | Relación moderada dentro del bloque de tamaño |
| precio – habitaciones | 0.269 | Sorprendentemente débil |
| estrato – habitaciones | -0.086 | Negativa: más habitaciones, menor estrato |
| precio/m² – área construida | -0.272 | Negativa: economías de escala — el metro grande vale menos |
| precio/m² – habitaciones | -0.357 | Negativa y notable: subdividir en alcobas destruye valor unitario |
Gracias a la Figura 17 y Tabla 12 podemos concluir que el número de habitaciones, que es la primera variable que un comprador suele mencionar, es el peor predictor del precio de todo el conjunto (r = 0,269), ya que se relaciona negativamente con el estrato (r = −0,086) y, de forma mucho más marcada, con el precio por metro cuadrado (r = −0,357). La explicación es de mercado: en los estratos altos el metraje se destina a espacios sociales, closets y zonas de servicio, mientras que en los estratos bajos la misma área se subdivide en más alcobas.
Ademas que el precio por metro cuadrado correlaciona negativamente con el área (r = −0,272), el mercado paga, de modo que el metro marginal de un inmueble grande vale menos que el de uno pequeño.
| Zona | Anuncios | % oferta | Precio mediano (M) | Área mediana (m²) | Precio/m² (M) | % casas | Estrato modal |
|---|---|---|---|---|---|---|---|
| Zona Oeste | 1198 | 14.4 | 580 | 165.5 | 3.70 | 14.1 | 6 |
| Zona Sur | 4726 | 56.8 | 320 | 113.0 | 2.69 | 41.0 | 5 |
| Zona Norte | 1920 | 23.1 | 300 | 107.0 | 2.22 | 37.6 | 5 |
| Zona Centro | 124 | 1.5 | 297 | 160.0 | 1.53 | 80.6 | 3 |
| Zona Oriente | 351 | 4.2 | 210 | 160.0 | 1.32 | 82.3 | 3 |
En la Figura 18 y tabla 13 podemos observar que la Zona Oeste es la más cara del mercado (mediana 580 M y $3,69 M/m2) pese a tener solo el 14,4 % de la oferta, y la Zona Oriente la más económica (210 M y 1,32 M/m2): una diferencia de 2,8 veces en el valor del metro cuadrado dentro de una misma ciudad.
El dato de gestión está en la comparación Centro–Norte: ambas tienen un precio total mediano prácticamente idéntico (297 M frente a 300 M), pero los inmuebles del Centro son un 50 % más grandes (160 m2 frente a 107 m2). Dando como consecuencia un precio por metro de 1,53 M en el Centro contra 2,23 M en el Norte.
La base registra 388 barrios distintos tras la normalización de la sección 2.1.3, pero la oferta está muy concentrada: Valle del Lili aporta 1.009 anuncios, el 12,1 % del total, y los veinte primeros barrios suman el 56,4 % del mercado. Esta concentración es relevante para la estrategia de inventario y se retoma en las conclusiones.
El ACP busca reducir las cinco variables cuantitativas de caracterización física a un número menor de dimensiones no correlacionadas que retengan la mayor parte de la información, este se trabaja sobre la matriz de correlaciones, obligatorio ya que preciom está en millones y banios` en unidades, sin estandarizar, el precio dominaría el primer eje por pura escala.
El número de componentes siempre es igual al número de variables activas (5), porque el ACP no descarta información.
# Vector propio de cada componente: coeficientes de la combinación lineal.
# Se obtienen dividiendo las coordenadas de las variables por la raíz del valor propio.
vectores <- sweep(res.pca$var$coord, 2, sqrt(res.pca$eig[1:5, 1]), "/")
round(vectores, 3)## Dim.1 Dim.2 Dim.3 Dim.4 Dim.5
## preciom 0.474 -0.358 -0.449 -0.094 0.660
## areaconst 0.494 0.110 -0.385 0.613 -0.469
## parqueaderos 0.401 -0.539 0.717 0.173 -0.067
## banios 0.496 0.140 -0.028 -0.754 -0.407
## habitaciones 0.353 0.741 0.367 0.132 0.417
| Variable | Componente 1 | Componente 2 | Componente 3 | Componente 4 | Componente 5 |
|---|---|---|---|---|---|
| preciom | 0.474 | -0.358 | -0.449 | -0.094 | 0.660 |
| areaconst | 0.494 | 0.110 | -0.385 | 0.613 | -0.469 |
| parqueaderos | 0.401 | -0.539 | 0.717 | 0.173 | -0.067 |
| banios | 0.496 | 0.140 | -0.028 | -0.754 | -0.407 |
| habitaciones | 0.353 | 0.741 | 0.367 | 0.132 | 0.417 |
Leyendo la primera columna de la Tabla 14, el componente 1 es
\[C_1 = 0{,}474\,z_{\text{precio}} + 0{,}494\,z_{\text{área}} + 0{,}401\,z_{\text{parq}} + 0{,}496\,z_{\text{baños}} + 0{,}353\,z_{\text{hab}}\]
Los cinco coeficientes son positivos y de magnitud parecida, entre 0,35 y 0,50, el primer componente es prácticamente un promedio ponderado de las cinco características, Un inmueble puntúa alto si es grande, caro, con muchos baños y parqueaderos a la vez.
El segundo, en cambio, contrapone unas variables a otras:
\[C_2 = -0{,}358\,z_{\text{precio}} + 0{,}110\,z_{\text{área}} - 0{,}539\,z_{\text{parq}} + 0{,}140\,z_{\text{baños}} + 0{,}741\,z_{\text{hab}}\]
Aquí habitaciones pesa +0,741 mientras parqueaderos pesa −0,539 y precio −0,358. Esa oposición de signos es lo que convierte al segundo componente en un contraste y no en otro índice de tamaño.
La composicion de los 5 componentes puede apreciarse mejor en la tabla 14 y la figura 20.
| Valor propio | % de varianza | % acumulado | Criterio de Kaiser | |
|---|---|---|---|---|
| comp 1 | 3.202 | 64.038 | 64.04 | Se retiene (λ > 1) |
| comp 2 | 0.930 | 18.594 | 82.63 | — |
| comp 3 | 0.401 | 8.012 | 90.64 | — |
| comp 4 | 0.290 | 5.806 | 96.45 | — |
| comp 5 | 0.177 | 3.550 | 100.00 | — |
Se retienen dos componentes, por convergencia de tres criterios: el de Kaiser (λ₁ = 3,202 > 1; λ2 = 0,930 ≈ 1), el codo presente en la Figura 21, que se produce nítidamente en la tercera dimensión, y el umbral práctico del 80 % de inercia acumulada cuyos valores se pueden apreciar mas facilmente en la Tabla 15, alcanzando estosen la segunda un 82,6 %.
| Variable | Corr. Dim1 | Contrib. Dim1 (%) | cos² Dim1 | Corr. Dim2 | Contrib. Dim2 (%) | cos² Dim2 |
|---|---|---|---|---|---|---|
| preciom | 0.849 | 22.5 | 0.720 | -0.345 | 12.8 | 0.119 |
| areaconst | 0.884 | 24.4 | 0.781 | 0.106 | 1.2 | 0.011 |
| parqueaderos | 0.717 | 16.1 | 0.514 | -0.520 | 29.1 | 0.270 |
| banios | 0.887 | 24.6 | 0.787 | 0.135 | 2.0 | 0.018 |
| habitaciones | 0.632 | 12.5 | 0.399 | 0.715 | 54.9 | 0.511 |
Todas las variables activas cargan positivamente sobre el primer eje, con correlaciones entre 0,63 y 0,89 y contribuciones muy equilibradas (12,5 % a 24,6 %). Es un típico efecto tamaño, los inmuebles se ordenan de los más pequeños, económicos y con menos dotación a los más grandes, caros y equipados. Baños (0,887), área (0,884) y precio (0,849) son los mejores representados, tal como se aprecia en la Tabla 16.
El segundo eje es el interesante, porque opone variables suceso que se demuestra en la Figura 22:
Un inmueble con puntuación alta en Dim2 tiene muchas habitaciones para su tamaño y pocos parqueaderos, uno con puntuación baja tiene pocas habitaciones pero mucho parqueadero y precio alto. La proyección de la variable ilustrativa estrato (r = +0,461 en Dim1, r = −0,489 en Dim2) confirma la lectura: el estrato alto se sitúa en el lado de pocos-cuartos-mucho-parqueadero**.
La separación de estratos que se observa en la Figura 23 sobre el eje horizontal es clara y gradual, sin cortes abruptos, el mercado es un continuo de valor, no un conjunto de compartimentos estancos, en el panel de casas se aprecia además una cola superior casas de estrato 3 y 4 con muchas habitaciones.
Los tres ejes restantes suman apenas el 17,4 % de la inercia y ninguno alcanza el umbral de Kaiser, lo que desde un punto de vista estadistico justifica su descarte, aun así conviene decir qué contiene cada uno.
Componente 3 (8,0 %) — parqueadero sin tamaño. Está gobernado por parqueaderos (coeficiente +0,717, contribución 51,4 %), contrapuesto a preciom (−0,449) y areaconst (−0,385). Separa inmuebles con más parqueaderos de los que su tamaño y precio harían esperar.
Componente 4 (5,8 %) — área frente a baños. Opone banios (−0,754) a areaconst (+0,613): distingue inmuebles amplios con pocos baños de inmuebles compactos con muchos, recoge diferencias de distribución interna que ninguna otra variable de la base explica.
Componente 5 (3,6 %) — precio no explicado por lo físico. preciom carga +0,660 frente a areaconst (−0,469) y banios (−0,407). Captura el precio que no se justifica por las características medidas, lo que en el mercado real aportarían la antigüedad, el estado de los acabados o la ubicación exacta dentro del barrio, variables que la base no registra.
Se segmentaron los inmuebles mediante k-means sobre las cinco variables activas estandarizadas. La estandarización es obligatoria por la misma razón que en el ACP: sin ella, preciom dominaría por completo el calculo de distancias.
Se eligió k-means y no un método jerárquico por el tamaño del dataset (8.319 registros)
| k | Reducción de la inercia intra (%) | Silueta media |
|---|---|---|
| 2 | 43.1 | 0.471 |
| 3 | 21.1 | 0.392 |
| 4 | 18.0 | 0.363 |
| 5 | 10.3 | 0.335 |
| 6 | 8.0 | 0.324 |
| 7 | 7.0 | 0.272 |
| 8 | 5.7 | 0.276 |
| 9 | 5.1 | — |
| 10 | 5.6 | — |
k = 4. La lectura de los dos criterios evidenciados en la Tabla 17 no es unánime.
El codo es claro: la ganancia marginal cae de 18,0 % (al pasar a k = 4) a 10,3 % (al pasar a k = 5) y a menos del 8 % en adelante. Añadir un quinto grupo ya no compra estructura.
La silueta es máxima en k = 2 (0,461) y decrece monotonamente. Esto es esperable, la silueta premia particiones globulares y bien separadas, y aquí los datos forman un continuo denso sin vacíos naturales. Con k = 2 el algoritmo simplemente parte el mercado en “caro/barato”, lo cual es estadísticamente limpio pero comercialmente inútil.
Se privilegia por tanto el criterio del codo reforzado por la interpretabilidad de negocio, que es el objetivo declarado del estudio. Con k = 4 se retiene el 63,2 % de la varianza total entre grupos.
Este comportamiento mencionado se puede apreciar en la Figura 24 donde k = n.
En la Tabla 18 se puede apreciar las caracteristicas generales de cada segmento establecido.
set.seed(2026)
km <- kmeans(Z, centers = 4, nstart = 50, iter.max = 100)
# Se reetiquetan los grupos por precio mediano ascendente
orden <- order(tapply(viv$preciom, km$cluster, median))
viv$segmento <- factor(match(km$cluster, orden), labels = paste0("S", 1:4))
round(100 * km$betweenss / km$totss, 1) # % de varianza explicada por la partición## [1] 63.2
| Segmento | n | % del mercado | Precio mediano (M) | Área (m²) | Habitaciones | Baños | Parqueaderos | Precio/m² (M) | % casas | Estrato modal | Zona sobre-representada |
|---|---|---|---|---|---|---|---|---|---|---|---|
| S1 | 4165 | 50.1 | 220 | 80 | 3 | 2 | 1 | 2.66 | 17 | 4 | Zona Norte (×1.22) |
| S2 | 761 | 9.1 | 430 | 300 | 7 | 5 | 1 | 1.45 | 98 | 3 | Zona Oriente (×4.24) |
| S3 | 2519 | 30.3 | 480 | 170 | 4 | 4 | 2 | 2.95 | 45 | 6 | Zona Oeste (×1.63) |
| S4 | 874 | 10.5 | 1150 | 367 | 4 | 5 | 4 | 2.91 | 71 | 6 | Zona Oeste (×2.02) |
La superposición del mapa de segmentos presente en la figura 26 con el plano del ACP es la prueba de coherencia entre las dos técnicas, los segmentos no se ordenan solo de izquierda a derecha (por valor), sino que uno de ellos se desplaza claramente hacia arriba en el eje de densidad de habitaciones, ocupando un espacio que ninguna clasificación por precio habría detectado.
| 3 | 4 | 5 | 6 | |
|---|---|---|---|---|
| S1 | 24.5 | 37.0 | 32.8 | 5.7 |
| S2 | 41.0 | 24.4 | 28.9 | 5.7 |
| S3 | 4.6 | 14.9 | 39.3 | 41.2 |
| S4 | 0.5 | 3.1 | 19.9 | 76.5 |
| Zona Centro | Zona Norte | Zona Oeste | Zona Oriente | Zona Sur | |
|---|---|---|---|---|---|
| S1 | 1.4 | 28.0 | 7.4 | 4.4 | 58.7 |
| S2 | 5.0 | 25.2 | 5.5 | 17.9 | 46.4 |
| S3 | 1.0 | 18.9 | 23.5 | 1.2 | 55.4 |
| S4 | 0.2 | 9.5 | 29.1 | 0.1 | 61.1 |
A continuacion en la Tabla 21 se evidencia un resumen de esta lectura.
| Segmento | Nombre propuesto | Rasgo que lo define | Uso estratégico |
|---|---|---|---|
| S1 | Entrada / renta urbana | Inmuebles pequeños, mayoritariamente apartamentos; el volumen del mercado | Rotación alta, inversión para arriendo, producto de captación |
| S2 | Familiar denso | Área grande con muchas habitaciones y poco parqueadero; casi todo casas de estrato bajo | Nicho de mayor margen por m²; candidato a remodelación y subdivisión |
| S3 | Consolidado medio-alto | Buen tamaño con dotación completa; el corazón del mercado de estrato 5-6 | Base estable de la operación; menor riesgo de inventario |
| S4 | Premium | Máximo en todas las variables; área y parqueaderos muy por encima de la media | Bajo volumen, alto ticket; requiere fuerza comercial especializada |
El segmento S2 (familiar denso), el cual es posible observar en la Tabla 19 es el hallazgo operativo del análisis. Con 761 inmuebles (9,1 % del mercado), combina el área mediana más alta después del segmento premium (300 m2) con el precio por metro cuadrado más bajo de todos 1,45 M/m2, frente a 2,95 M/m2 del segmento consolidado. Son casas en un 98 %, con siete alcobas de mediana, un solo parqueadero y estrato modal 3.
Territorialmente no es el más numeroso en ninguna zona esto se demuestra en la Tabla 20, mayor volumen está en Zona Sur pero está fuertemente sobre-representado esto se demuestra en la FIgura 27: aparece 4,24 veces más de lo esperado en Zona Oriente y 3,35 veces más en Zona Centro, precisamente las dos zonas que el análisis de correspondencias identificará como atípicas.
Su relevancia comercial es doble: es donde el descuento por metro es mayor un inmueble de S2 se compra a la mitad del precio unitario de uno de S3— y, por su tamaño, es el producto con más recorrido para remodelación, subdivisión o cambio de uso.
A continuacion se realiza el calculo de la inercia y las medidas de asociacion lo cual se muestra en la Tabla 22.
| Tabla analizada | Chi² | gl | Valor p | Inercia total | V de Cramér | C de Pearson | C máximo | C corregido |
|---|---|---|---|---|---|---|---|---|
| zona × estrato | 3830.4 | 12 | < 2,2 · 10⁻¹⁶ | 0.4604 | 0.392 | 0.561 | 0.866 | 0.648 |
| zona × rango de precio | 1156.0 | 12 | < 2,2 · 10⁻¹⁶ | 0.1390 | 0.215 | 0.349 | 0.866 | 0.403 |
| tipo × zona | 690.9 | 4 | < 2,2 · 10⁻¹⁶ | 0.0831 | 0.288 | 0.277 | 0.707 | 0.392 |
| tipo × estrato | 224.3 | 3 | < 2,2 · 10⁻¹⁶ | 0.0270 | 0.164 | 0.162 | 0.707 | 0.229 |
| barrio (top 20) × rango de precio | 3381.0 | 57 | < 2,2 · 10⁻¹⁶ | 0.7212 | 0.490 | 0.647 | 0.866 | 0.747 |
Gracias a las Tabla 22 y la Figura 28 podemos afirmar que se rechaza la hipótesis de independencia con p < 0,001, de modo que en todas hay inercia que descomponer.
barrio × rango de precio: es la más fuerte (inercia 0,721; V = 0,490; C* = 0,747). Era previsible: el barrio es la unidad geográfica más fina disponible y captura el precio mejor que cualquier agregado.
zona × estrato: viene inmediatamente después (inercia 0,460; V = 0,392; C* = 0,648) y es la que se toma como análisis principal, porque con solo 5 × 4 categorías admite una lectura completa del mapa, mientras que la de barrios tiene 20 filas.
zona × rango de precio: (inercia 0,139) y tipo × zona (0,083) son asociaciones moderadas, y tipo × estrato (0,027) la más débil de todas, saber si un inmueble es casa o apartamento dice poco sobre su estrato.
| 3 | 4 | 5 | 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 |
| 3 | 4 | 5 | 6 | |
|---|---|---|---|---|
| Zona Centro | 84.7 | 11.3 | 3.2 | 0.8 |
| Zona Norte | 29.8 | 21.2 | 40.1 | 9.0 |
| Zona Oeste | 4.5 | 7.0 | 24.2 | 64.3 |
| Zona Oriente | 96.9 | 2.3 | 0.6 | 0.3 |
| Zona Sur | 8.1 | 34.2 | 35.7 | 22.1 |
## eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.322 69.966 69.97
## dim 2 0.127 27.680 97.65
## dim 3 0.011 2.354 100.00
## [1] 0.4604
La suma de los valores propios es 0,4604, idéntica al cociente \(\chi^2/n = 3830{,}4/8319\) de la Tabla 22. Es la comprobación de que la inercia que descompone el AC es exactamente la misma cantidad que mide la prueba \(\chi^2\): el AC es una descomposición geométrica del estadístico de independencia.
La figura 29 es la lectura eje por eje de las mismas coordenadas que resume el mapa perceptual siguiente. Tiene una ventaja sobre el biplot que al separar las dimensiones evita el error frecuente de leer distancias directas entre una fila y una columna.
| Categoría | Tipo | Dim 1 | Contrib. D1 (%) | Dim 2 | Contrib. D2 (%) |
|---|---|---|---|---|---|
| Zona Centro | Zona | 1.725 | 13.8 | 0.364 | 1.5 |
| Zona Norte | Zona | 0.390 | 10.9 | -0.147 | 3.9 |
| Zona Oeste | Zona | -0.569 | 14.5 | 0.783 | 69.2 |
| Zona Oriente | Zona | 2.015 | 53.2 | 0.537 | 9.6 |
| Zona Sur | Zona | -0.209 | 7.7 | -0.188 | 15.8 |
| 3 | Estrato | 1.187 | 76.3 | 0.207 | 5.9 |
| 4 | Estrato | -0.154 | 1.9 | -0.380 | 29.0 |
| 5 | Estrato | -0.132 | 1.8 | -0.204 | 10.8 |
| 6 | Estrato | -0.519 | 20.0 | 0.539 | 54.4 |
Gracias a la tabla 25 y la Figura 30 podemos afirmar que Las dos dimensiones retienen el 97,6 % de la inercia total, de modo que el mapa plano es una representación muy completa de la tabla.
Dimensión 1 (70,0 %) — gradiente socioeconómico. Está construida esencialmente por la oposición entre el estrato 3 (contribución 76,3 %) y el estrato 6 (20,0 %). Del lado de las filas, la Zona Oriente aporta el 53,2 % de la inercia del eje, es, con diferencia, la zona más atípica del mercado. Sus 351 anuncios son 96,9 % estrato 3, una homogeneidad que ninguna otra zona presenta.
Dimensión 2 (27,7 %) — separación de los estratos intermedios, Aísla el estrato 6 (contribución 54,4 %) y la Zona Oeste (69,2 %) del bloque de estratos 4–5.
La estructura territorial del mercado se resume en tres bloques: (i) Zona Oriente y Centro estrato 3, mercado de vivienda económica; (ii) Zona Oeste ↔︎ estrato 6, mercado de lujo, con el 64,3 % de sus anuncios en estrato 6, y (iii) Zonas Sur y Norte, próximas al origen, que son las zonas de perfil promedio es decir, las únicas que ofrecen producto en todos los estratos y, por tanto, las de mayor flexibilidad comercial.
| Económico | Medio | Alto | Premium | |
|---|---|---|---|---|
| Zona Centro | 26.6 | 45.2 | 22.6 | 5.6 |
| Zona Norte | 31.5 | 31.2 | 26.5 | 10.8 |
| Zona Oeste | 6.4 | 12.9 | 34.4 | 46.3 |
| Zona Oriente | 47.9 | 41.6 | 9.7 | 0.9 |
| Zona Sur | 20.7 | 36.9 | 23.3 | 19.1 |
| eigenvalue | percentage of variance | cumulative percentage of variance | |
|---|---|---|---|
| dim 1 | 0.125 | 89.652 | 89.65 |
| dim 2 | 0.011 | 8.194 | 97.85 |
| dim 3 | 0.003 | 2.154 | 100.00 |
Tal como se observa en la figura 31 y en las Tablas 26 y 27 una sola dimensión concentra el 89,7 % de la inercia, la relación entre zona y precio es esencialmente unidimensional, un simple gradiente caro–barato, el eje ordena la Zona Oeste (coordenada +0,775, junto a Premium: +0,581) en un extremo, y la Zona Oriente (−0,727, junto a económico: −0,386) en el otro. Zona Sur queda casi en el origen (−0,036), confirmando que es el mercado de referencia de la ciudad.
| Barrio | Anuncios | Precio mediano (M) | Área (m²) | Precio/m² (M) | Estrato modal |
|---|---|---|---|---|---|
| santa teresita | 263 | 750.0 | 194 | 4.08 | 6 |
| normandía | 154 | 621.5 | 166 | 3.95 | 6 |
| cristales | 237 | 470.0 | 125 | 3.85 | 6 |
| pance | 412 | 780.0 | 199 | 3.80 | 6 |
| urbanización la flora | 83 | 360.0 | 104 | 3.54 | 5 |
| aguacatal | 109 | 690.0 | 184 | 3.42 | 6 |
| hacienda | 166 | 327.5 | 98 | 3.28 | 5 |
| ciudad jardín | 518 | 670.0 | 200 | 3.27 | 6 |
| flora | 369 | 350.0 | 105 | 3.08 | 5 |
| valle del lili | 1009 | 235.0 | 76 | 2.92 | 4 |
| prados del norte | 127 | 229.0 | 75 | 2.67 | 4 |
| ingenio | 204 | 356.0 | 129 | 2.62 | 5 |
| caney | 297 | 230.0 | 85 | 2.50 | 4 |
| acopi | 158 | 375.0 | 136 | 2.45 | 5 |
| zona sur | 74 | 325.0 | 133 | 2.44 | 5 |
| refugio | 122 | 240.0 | 94 | 2.35 | 4 |
| nueva tequendama | 73 | 350.0 | 140 | 2.32 | 5 |
| limonar | 135 | 370.0 | 160 | 2.15 | 5 |
| brisas de los | 82 | 125.0 | 60 | 2.00 | 3 |
| ciudad 2000 | 96 | 325.0 | 169 | 1.81 | 4 |
Gracias a la figura 32 y la tabla 28 podemos observar que las dos primeras dimensiones acumulan el 95,3 % de la inercia. La lectura del mapa distingue tres familias de barrios:
Polo premium (izquierda del eje 1): Pance (−1,110), Santa Teresita (−1,051), Ciudad Jardín (−0,872) y Normandía (−0,811). En los cuatro, más de la mitad de la oferta está en el rango superior (Pance 69 %, Santa Teresita 66 %, Ciudad Jardín 57 %, Normandía 55 %). Son también los cuatro primeros del ranking de precio por metro cuadrado de la Tabla 28, con Santa Teresita a la cabeza en 4,08 M/m2.
Polo económico (derecha): Brisas de los (+1,154), Valle del Lili (+0,826), Caney (+0,764) y Refugio (+0,630).
Barrios de perfil mixto (cerca del origen): Acopi, Ingenio, Limonar y Urbanización La Flora, que ofrecen producto en varios rangos simultáneamente y son, por tanto, los de mayor amplitud de cartera para un mismo corredor.
Por otra parte vale la pena destacar que Valle del Lili aporta 1.009 anuncios el 12,1 % de todo el mercado, siendo el barrio con más oferta pero se sitúa en el polo económico, con 2,92 M/m2 frente a los 4,08 M/m2 de Santa Teresita. Un barrio con esa densidad de oferta y precios contenidos es simultáneamente el de mayor liquidez y el de mayor presión competitiva: es donde más rápido se vende y donde menos margen hay por unidad.
El AC simple solo admite dos variables. Para examinar simultáneamente tipo, zona, estrato, rango de precio y rango de área se recurre al ACM.
datos_acm <- viv %>%
select(tipo, zona, estrato, rango_precio, rango_area) %>%
mutate(across(everything(), ~factor(as.character(.))))
res.mca <- MCA(datos_acm, graph = FALSE)
round(res.mca$eig[1:5, ], 3)## eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.508 18.145 18.14
## dim 2 0.365 13.041 31.19
## dim 3 0.326 11.631 42.82
## dim 4 0.266 9.501 52.32
## dim 5 0.222 7.915 60.23
| Dim 1 | Dim 2 | |
|---|---|---|
| tipo | 0.158 | 0.256 |
| zona | 0.196 | 0.355 |
| estrato | 0.573 | 0.551 |
| rango_precio | 0.880 | 0.292 |
| rango_area | 0.732 | 0.372 |
En la Figura 33 se aprecia que el eje 1 está gobernado por rango_precio (η2 = 0,880) y rango_area (η2 = 0,732): es de nuevo el eje de valor y tamaño, y sobre él se alinean Económico + Pequeña + estrato 3 en un extremo y Premium + Muy grande + estrato 6 + Zona Oeste en el otro. El eje 2 lo dominan estrato (η2 = 0,551) y zona (η2 = 0,355),con la Zona Oriente (coordenada +2,482) y la Zona Centro (+1,817) proyectadas muy lejos del resto: son mercados con dinámica propia, no versiones “más baratas” del mercado principal.
El ACM confirma así, con las cinco variables a la vez, lo que el ACP y el AC habían mostrado por separado: el mercado se ordena primero por valor y después por territorio.
| Técnica | Resultado principal | Aporte a la decisión |
|---|---|---|
| Procesamiento | Little rechaza MCAR (χ²=743,1; gl=23); mecanismo MAR y ausencia estructural en parqueaderos | Garantiza que las conclusiones no son artefactos de datos sucios o mal imputados |
| AED | Asimetría persistente; precio–habitaciones r = 0,269; precio/m²–área r = −0,272 | Fija el precio/m² y la mediana como indicadores de gestión |
| ACP | 2 componentes retienen 82,6 %: escala/valor (64,0 %) y densidad de habitaciones (18,6 %) | Demuestra que habitaciones y confort son dimensiones opuestas, no acumulativas |
| Conglomerados | 4 segmentos que explican el 63,2 % de la varianza total | Define cuatro políticas comerciales diferenciadas |
| AC simple | zona × estrato: V = 0,392; 97,6 % de inercia en dos ejes | Identifica Oriente y Oeste como mercados especializados; Sur y Norte como flexibles |
| ACM | Eje 1 = valor (η² precio 0,880); eje 2 = territorio (η² estrato 0,551) | Confirma la jerarquía: primero valor, después territorio |
Tal como se puede observar en la Tabla 30 las técnicas convergen, y esa convergencia es la mejor garantía de validez de los hallazgos, la segunda dimensión del ACP (habitaciones frente a parqueaderos) reaparece como el segmento S2 en el análisis de conglomerados y en el ACM, como la posición excéntrica de la Zona Oriente y del estrato 3. Se trata del mismo fenómeno observado con tres instrumentos distintos, existe un submercado de vivienda amplia y densamente habitada que el precio total no distingue del resto.
El procesamiento no fue un trámite, este cambió la lectura del problema, La prueba de Little rechazó la aleatoriedad completa de los datos faltantes (\(\chi^2 = 743{,}12\); gl = 23; p < 0,001) y la regresión logística mostró que la ausencia de parqueaderos`depende del estrato con una razón de momios de 0,36 por escalón.
El mercado inmobiliario de Cali es bidimensional, el 82,6 % de la variabilidad de las características físicas se explica con dos ejes: escala/valor del inmueble (64,0 %) y densidad de habitaciones frente a confort (18,6 %). Cualquier modelo de valoración que use solo el primero ignora casi una quinta parte de la información disponible.
El número de habitaciones es un mal indicador de valor. Con r = 0,269 frente al precio, r = −0,086 frente al estrato y r = −0,357 frente al precio por metro cuadrado, habitaciones mide densidad de ocupación y no calidad. Los verdaderos predictores del precio son el área (0,711), los baños (0,684), los parqueaderos (0,646) y el estrato (0,623), cuatro variables de magnitud muy similar.
Existen cuatro segmentos operativamente distintos, que explican el 63,2 % de la varianza total: entrada/renta urbana (el volumen), familiar denso (el margen por m2), consolidado medio-alto (la estabilidad) y premium (el ticket alto). Cada uno exige una política de precio, inventario y fuerza comercial diferente.
La localización determina el estrato con fuerza alta (V de Cramér = 0,392, \(\chi^2\) = 3.830 con 12 gl, p < 0,001). Zona Oriente es 96,9 % estrato 3 y Zona Oeste es 64,3 % estrato 6: son mercados especializados. Zona Sur y Zona Norte, con perfiles próximos al promedio, son las únicas con presencia en todos los estratos.
El precio por metro cuadrado revela oportunidades que el precio total oculta, el rango va de 1,70 M/m2 en estrato 3 a 3,66 M/m2 en estrato 6 y de 1,32 M/m2 en Zona Oriente a 3,69 M/m2 en Zona Oeste. Además decrece con el tamaño (r = −0,272): el segmento familiar denso combina área alta con 1,45 M/m2, la mitad del precio unitario del segmento consolidado, y ahí reside el mayor potencial de arbitraje del mercado.
La concentración de la oferta es un riesgo. El 56,8 % de los anuncios está en la Zona Sur y un solo barrio (Valle del Lili) representa el 12,1 % del mercado; los veinte barrios más ofertados suman el 56,4 %. Una estrategia de inventario que replique esa distribución quedaría expuesta a la dinámica de un único submercado.
| # | Recomendación | Fundamento | Acción concreta |
|---|---|---|---|
| 1 | Adoptar el precio por m2 como indicador central de gestión | El precio total oculta el efecto tamaño; el precio/m2 tiene un CV de 39,6 % frente al 74,9 % del precio (Tablas 10 y 13) | Incorporar precio/m2 en el tablero comercial y fijar bandas de referencia por barrio |
| 2 | Construir el modelo de valoración sobre 4 variables, no sobre habitaciones | Área, baños, parqueaderos y estrato correlacionan entre 0,62 y 0,71 con el precio; habitaciones solo 0,27 (Tabla 12) | Priorizar la verificación en terreno de área, baños y parqueaderos antes de publicar |
| 3 | Abrir una línea de negocio sobre el segmento familiar denso (S2) | Combina 300 m2 de área mediana con $1,45 M/m2, el precio unitario más bajo del mercado (Tabla 18) | Programa de captación de casas amplias de estrato 3-4 para remodelación o cambio de uso |
| 4 | Diversificar el inventario hacia Zona Norte y Zona Oeste | El 56,8 % de la oferta está en Zona Sur; Oeste tiene la mediana más alta con solo el 14,4 % de los anuncios (Tabla 13) | Fijar cuotas de captación por zona que no repliquen la distribución actual de la oferta |
| 5 | Diferenciar el guion comercial por segmento | Los cuatro segmentos difieren en rotación, ticket y perfil de comprador (Tablas 18 y 21) | Cuatro guiones de venta y cuatro políticas de descuento, una por segmento |
| 6 | Instrumentar la captura de datos: parqueaderos y piso | El 19,26 % de ausencia en parqueaderos se explica porque el formulario no admite el valor 0 (sección 2.4) | Volver obligatorios ambos campos en el formulario, admitiendo ‘0’ como opción explícita |
| Segmento | Tipo | n | Precio mediano (M) | Área (m²) | Precio/m² (M) | Hab. | Baños | Parq. |
|---|---|---|---|---|---|---|---|---|
| S1 | Apartamento | 3442 | 220 | 75.0 | 2.76 | 3 | 2 | 1 |
| S1 | Casa | 723 | 230 | 120.0 | 1.88 | 3 | 2 | 1 |
| S2 | Apartamento | 17 | 575 | 300.0 | 1.40 | 5 | 5 | 1 |
| S2 | Casa | 744 | 430 | 300.0 | 1.45 | 7 | 4 | 1 |
| S3 | Apartamento | 1385 | 530 | 145.0 | 3.65 | 3 | 4 | 2 |
| S3 | Casa | 1134 | 440 | 220.0 | 2.11 | 4 | 4 | 2 |
| S4 | Apartamento | 256 | 1250 | 285.5 | 4.38 | 3 | 5 | 3 |
| S4 | Casa | 618 | 990 | 420.0 | 2.43 | 4 | 5 | 4 |
| preciom | areaconst | parqueaderos | banios | habitaciones | estrato | precio_m2 | |
|---|---|---|---|---|---|---|---|
| preciom | 1.000 | 0.711 | 0.646 | 0.684 | 0.269 | 0.623 | 0.383 |
| areaconst | 0.711 | 1.000 | 0.504 | 0.703 | 0.567 | 0.296 | -0.272 |
| parqueaderos | 0.646 | 0.504 | 1.000 | 0.525 | 0.189 | 0.513 | 0.224 |
| banios | 0.684 | 0.703 | 0.525 | 1.000 | 0.594 | 0.422 | 0.033 |
| habitaciones | 0.269 | 0.567 | 0.189 | 0.594 | 1.000 | -0.086 | -0.357 |
| estrato | 0.623 | 0.296 | 0.513 | 0.422 | -0.086 | 1.000 | 0.562 |
| precio_m2 | 0.383 | -0.272 | 0.224 | 0.033 | -0.357 | 0.562 | 1.000 |
| Dim.1 | Dim.2 | Dim.3 | Dim.4 | Dim.5 | |
|---|---|---|---|---|---|
| preciom | 0.849 | -0.345 | -0.285 | -0.051 | 0.278 |
| areaconst | 0.884 | 0.106 | -0.244 | 0.330 | -0.198 |
| parqueaderos | 0.717 | -0.520 | 0.454 | 0.093 | -0.028 |
| banios | 0.887 | 0.135 | -0.018 | -0.406 | -0.171 |
| habitaciones | 0.632 | 0.715 | 0.233 | 0.071 | 0.176 |
| Dim.1 | Dim.2 | Dim.3 | Dim.4 | Dim.5 | |
|---|---|---|---|---|---|
| preciom | 22.49 | 12.79 | 20.20 | 0.89 | 43.62 |
| areaconst | 24.40 | 1.22 | 14.82 | 37.55 | 22.02 |
| parqueaderos | 16.06 | 29.09 | 51.40 | 3.00 | 0.45 |
| banios | 24.58 | 1.96 | 0.08 | 56.83 | 16.55 |
| habitaciones | 12.47 | 54.94 | 13.50 | 1.73 | 17.36 |
| Dim.1 | Dim.2 | Dim.3 | Dim.4 | Dim.5 | |
|---|---|---|---|---|---|
| preciom | 0.720 | 0.119 | 0.081 | 0.003 | 0.077 |
| areaconst | 0.781 | 0.011 | 0.059 | 0.109 | 0.039 |
| parqueaderos | 0.514 | 0.270 | 0.206 | 0.009 | 0.001 |
| banios | 0.787 | 0.018 | 0.000 | 0.165 | 0.029 |
| habitaciones | 0.399 | 0.511 | 0.054 | 0.005 | 0.031 |
piso| 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | NA | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Apartamento | 430 | 512 | 573 | 545 | 564 | 243 | 200 | 211 | 146 | 128 | 84 | 83 | 1381 |
| Casa | 430 | 938 | 524 | 62 | 3 | 2 | 4 | 0 | 0 | 2 | 0 | 0 | 1254 |
Se incluye como anexo para dejar constancia del diagnóstico, aunque la variable no participa en ningún análisis multivariado por las razones expuestas en la sección 2.3.
## R version 4.4.1 (2024-06-14 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
##
##
## locale:
## [1] LC_COLLATE=Spanish_Colombia.utf8 LC_CTYPE=Spanish_Colombia.utf8
## [3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C
## [5] LC_TIME=Spanish_Colombia.utf8
##
## time zone: America/Bogota
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] mice_3.19.0 naniar_1.1.0 gridExtra_2.3.1 corrplot_0.95
## [5] cluster_2.1.8.3 factoextra_2.2.0 FactoMineR_2.16 kableExtra_1.4.0
## [9] knitr_1.51 scales_1.4.0 ggplot2_4.0.3 tidyr_1.3.2
## [13] dplyr_1.2.1
##
## loaded via a namespace (and not attached):
## [1] Rdpack_2.6.4 rlang_1.3.0 magrittr_2.0.5
## [4] otel_0.2.0 compiler_4.4.1 mgcv_1.9-1
## [7] systemfonts_1.3.1 vctrs_0.7.3 stringr_1.6.0
## [10] sysfonts_0.8.9 pkgconfig_2.0.3 shape_1.4.6.1
## [13] fastmap_1.2.0 backports_1.5.1 labeling_0.4.3
## [16] rmarkdown_2.30 nloptr_2.2.1 visdat_0.6.0
## [19] purrr_1.2.2 xfun_0.60 glmnet_4.1-10
## [22] jomo_2.7-6 showtext_0.9-8 cachem_1.1.0
## [25] jsonlite_2.0.0 flashClust_1.1-4 pan_1.9
## [28] broom_1.0.13 irlba_2.3.7 R6_2.6.1
## [31] bslib_0.9.0 stringi_1.8.9 RColorBrewer_1.1-3
## [34] car_3.1-3 boot_1.3-30 rpart_4.1.23
## [37] jquerylib_0.1.4 estimability_2.0.0 Rcpp_1.1.2
## [40] iterators_1.0.14 Matrix_1.7-0 splines_4.4.1
## [43] nnet_7.3-19 tidyselect_1.2.1 abind_1.4-8
## [46] rstudioapi_0.17.1 yaml_2.3.12 ggtext_0.1.2
## [49] codetools_0.2-20 lattice_0.22-7 tibble_3.3.1
## [52] withr_3.0.3 S7_0.2.2 evaluate_1.0.5
## [55] survival_3.6-4 norm_1.0-11.1 xml2_1.5.1
## [58] pillar_1.11.1 ggpubr_1.0.0 carData_3.0-5
## [61] DT_0.34.0 foreach_1.5.2 reformulas_0.4.0
## [64] generics_0.1.4 minqa_1.2.8 xtable_1.8-4
## [67] leaps_3.2 glue_1.8.1 emmeans_2.0.4
## [70] scatterplot3d_0.3-45 tools_4.4.1 lme4_1.1-37
## [73] ggsignif_0.6.4 mvtnorm_1.4-2 grid_4.4.1
## [76] rbibutils_2.3 nlme_3.1-164 showtextdb_3.0
## [79] Formula_1.2-5 cli_3.6.6 textshaping_1.0.4
## [82] viridisLite_0.4.3 svglite_2.2.2 gtable_0.3.6
## [85] rstatix_1.1.0 sass_0.4.10 digest_0.6.39
## [88] ggrepel_0.9.8 htmlwidgets_1.6.4 farver_2.1.2
## [91] htmltools_0.5.9 lifecycle_1.0.5 multcompView_0.1-12
## [94] mitml_0.4-5 gridtext_0.1.6 MASS_7.3-60.2
Informe elaborado en R Markdown · Modelos Estadísticos · 2026