# 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 Datos

1.1 Origen y estructura

data("vivienda", package = "paqueteMODELOS")
viv0 <- as.data.frame(vivienda)
dim(viv0)
## [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

1.2 Clasificación de las variables

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.

Tabla 1. Descripción, naturaleza y tipo de las variables del conjunto de datos
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

1.2.1 Estrato y piso

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:

estrato <- factor(estrato, levels = 3:6, ordered = TRUE)

La variable de piso también es cualitativa ordinal por lo que se trata como una variable categórica

1.3 Normalización de las etiquetas de texto

# 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

2 Procesamiento de datos

2.1 Inconsistencias

2.1.1 Registros duplicados y vacíos

Cada fila corresponde a un anuncio independiente, por lo que la informacion presente en cada uno no deberia repetirse.

cat("Registros completamente vacíos:", sum(is.na(viv0$id)), "\n")
## Registros completamente vacíos: 3
cat("Filas duplicadas exactas:      ", sum(duplicated(viv0)), "\n")
## 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.

2.1.2 Valores imposibles variables cuantitativas

cat("Inmuebles con 0 baños:       ", sum(viv0$banios == 0, na.rm = TRUE), "\n")
## Inmuebles con 0 baños:        45
cat("Inmuebles con 0 habitaciones:", sum(viv0$habitaciones == 0, na.rm = TRUE), "\n")
## Inmuebles con 0 habitaciones: 66
cat("Áreas menores a 20 m²:       ", sum(viv0$areaconst < 20, na.rm = TRUE), "\n")
## Áreas menores a 20 m²:        0
cat("Precios no positivos:        ", sum(viv0$preciom <= 0, na.rm = TRUE), "\n")
## 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

2.2 Datos atípicos.

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)
}))
Tabla 2. Indicadores de tendencia central y porcentaje de atípicos por variable
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.

2.2.1 Datos atipicos por estrato

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)
}))
Tabla 3. Valores atípicos detectados con umbral global frente a umbral condicionado por estrato
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:

  • En preciom los atípicos caen de 552 a 340 (−38 %)** y en habitaciones de 822 a 572.
  • En banios, parqueaderos y areaconst los atípicos aumentan, demostrando la diferente configuaracion de los inmuebles.

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.

2.2.2 Tratamiento de datos atipicos

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)
Tabla 4. Umbrales y registros recortados dentro de cada 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

Tabla 5. Indicadores antes y después del tratamiento de valores atípicos
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.

2.3 Datos faltantes (NA)

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.

Tabla 6. Número y porcentaje de datos NA por variable
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.

  1. 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.

  2. Parqueaderos (19,26 %): Este presenta un patrón muy marcado por estrat que se evidencia en la tabla 7.

  3. 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.

Tabla 7. Ausencia de parqueaderos según estrato socioeconómico (%)
% con dato % sin dato
3 47.1 52.9
4 77.1 22.9
5 91.7 8.3
6 94.1 5.9

2.4 Identificación del mecanismo de datos faltantes

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.

mcar_test(viv[, cuant])

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.

2.4.1 Normalidad de las variables con datos faltantes

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.

2.4.2 Modelos de regresión logística sobre los indicadores de ausencia

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
summary(glm(hab_NA ~ preciom + areaconst + estrato, family = binomial, data = viv))$coefficients
##               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.

2.4.3 Conclusión sobre el mecanismo

Tabla 8. Mecanismo de ausencia identificado y tratamiento asignado
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.

2.5 Imputación de datos faltantes

2.5.1 Variables cuantitativas

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)
Tabla 9. Método de imputación asignado por mice a cada variable
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)

2.5.2 Diagnóstico de la imputación

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

2.5.3 Tratamiento de las variables cualitativas

Repecto a las variables cualitativas presentes en el dataset, ninguna de las cinco variables cualitativas requirió imputación:

2.6 Base de datos final

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.

Tabla 10. Medidas descriptivas de las variables cuantitativas de la base limpia
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.

Tabla 11. Descripción de las variables cualitativas de la base limpia
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.

3 Análisis exploratorio de datos

3.1 Panorama univariado

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.

3.2 Relación entre precio, área y estrato

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.

3.3 Estructura de correlaciones

Tabla 12. Correlaciones seleccionadas y su interpretación
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.

3.4 Comparación entre zonas

Tabla 13. Perfil comparado de las cinco zonas de la ciudad
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.

3.5 Concentración de la oferta por barrio

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.

4 Análisis de componentes principales

4.1 Planteamiento

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.

  • Variables activas: preciom, areaconst, parqueaderos, banios, habitaciones.
  • Variable cuantitativa ilustrativa: estrato (no participa en la construcción de los ejes, pero se proyecta para ayudar a interpretarlos).
datos_acp <- cbind(viv[, cuant],
                   estrato_num = as.numeric(as.character(viv$estrato)))
res.pca <- PCA(datos_acp, quanti.sup = 6, scale.unit = TRUE, graph = FALSE)

4.2 Creacion de los componentes

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
Tabla 14. Coeficientes de cada variable en los cinco componentes (vectores propios)
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.

4.3 Valores propios y dimensiones a retener

Tabla 15. Valores propios e inercia explicada por cada componente
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 %.

4.4 Interpretación de los ejes

Tabla 16. Correlaciones, contribuciones y calidad de representación (cos²)
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

4.4.1 Dimensión 1 — Escala y valor del inmueble (64,0 %)

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.

4.4.2 Dimensión 2 — Densidad de habitaciones frente a confort (18,6 %)

El segundo eje es el interesante, porque opone variables suceso que se demuestra en la Figura 22:

  • Lado positivo: habitaciones (r = +0,715, contribución 54,9 %).
  • Lado negativo: parqueaderos (r = −0,520, contribución 29,1 %) y preciom (r = −0,345).

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.

4.4.3 Componentes 3, 4 y 5

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.

5 Análisis de conglomerados

5.1 Estrategia

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)

Z <- scale(viv[, cuant]) # estandarización: media 0, desviación 1

5.2 Determinación del número de grupos

Tabla 17. Criterios para la elección del número de grupos
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.

5.3 Perfil de los cuatro segmentos

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
Tabla 18. Perfil descriptivo de los cuatro segmentos de mercado
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.

Tabla 19. Composición de cada segmento por estrato (% por fila)
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
Tabla 20. Composición de cada segmento por zona (% por fila)
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

5.4 Lectura comercial de los segmentos

A continuacion en la Tabla 21 se evidencia un resumen de esta lectura.

Tabla 21. Denominación comercial y uso estratégico de cada segmento
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.

6 Análisis de correspondencias

6.1 Fundamento, inercia y medidas de asociación

A continuacion se realiza el calculo de la inercia y las medidas de asociacion lo cual se muestra en la Tabla 22.

Tabla 22. Inercia y medidas de asociación de las tablas de contingencia
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.

6.2 AC 1 — Zona y estrato socioeconómico

Tabla 23. Tabla de contingencia zona × estrato (frecuencias)
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
Tabla 24. Perfiles fila: composición por estrato dentro de cada zona (%)
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
ca1 <- CA(t1, graph = FALSE)
round(ca1$eig, 3)  # valores propios = inercia por eje
##       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
sum(ca1$eig[, 1])  # inercia total = chi2 / n
## [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.

6.2.1 Gráfico de coordenadas

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.

Tabla 25. Coordenadas y contribuciones en el mapa zona × estrato
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.

6.3 AC 2 — Zona y nivel de precio

Tabla 26. Distribución del rango de precio dentro de cada zona (%)
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
Tabla 27. Inercia del AC zona × rango de precio
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.

6.4 AC 3 — Barrios y nivel de precio

Tabla 28. Perfil de los 20 barrios con mayor oferta, ordenados por precio/m²
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.

6.5 ACM — Análisis de correspondencias múltiple

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

Tabla 29. Razón de correlación (η²) de cada variable con los dos primeros ejes
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.

7 Síntesis integrada de resultados

Tabla 30. Convergencia de las técnicas aplicadas
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.

8 Conclusiones

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

9 Recomendaciones

Tabla 31. Recomendaciones, fundamento estadístico y acción concreta
# 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

10 Anexos

10.1 Anexo A — Descriptivos completos por segmento y tipo

Tabla A1. Perfil de cada segmento desagregado por tipo de vivienda
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

10.2 Anexo B — Matriz de correlaciones completa

Tabla B1. Matriz de correlaciones de Pearson
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

10.3 Anexo C — Resultados numéricos completos del ACP

Tabla C1. Coordenadas de las variables en los 5 ejes
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
Tabla C2. Contribuciones de las variables (%)
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
Tabla C3. Calidad de representación (cos²)
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

10.4 Anexo D — Distribución de la variable piso

Tabla D1. Distribución de piso por tipo de inmueble (NA = no reportado o no aplica)
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.

10.5 Anexo E — Información de la sesión

## 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