Introducción

Este informe presenta una evaluación del mercado inmobiliario basada en el procesamiento de datos reales de marketing mediante técnicas de análisis multivariado. El objetivo primordial es construir modelos estadísticos que permitan sintetizar la complejidad de la información recogida y descubrir los patrones subyacentes que rigen los precios de las viviendas ofertadas. A través de este análisis, se busca transformar los datos brutos en una estructura comprensible que facilite la interpretación de las tendencias del sector y proporcione conclusiones estratégicas derivadas de los resultados obtenidos.

1. Entendimiento de los datos

Una vez cargada la base debemos saber:

  • ¿Cuántos registros y atributos tiene el conjubto de datos?
  • ¿De qué tipo son los atributos?
  • Obtener una medida de dispersión y centralidad
  • Calcular la matriz de correlación de los atributos

Como paso previo al preprocesamiento de los datos, debemos:

  • Detectar si hay datos faltantes
  • Detectar si hay datos atípicos
  • Detectar si hay registros duplicados
library(ggplot2)
library(summarytools)
library(knitr)
library(mice)
library(FactoMineR)
library(factoextra)
library(gridExtra)
library(dplyr)
# devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
library(paqueteMODELOS)
library(corrplot)
library(tidyverse)

data("vivienda")

Cantidad de registros y atributos (filas y columnas)

Todos los atributos tienen la misma cantidad de registros

dim(vivienda)
## [1] 8322   13

Tipo de datos de cada atributo y estructura general

Se identifican valores faltantes (NA) en el atributo categórico piso. Adicional, la variable estrato está clasificada como dato numérico.

str(vivienda, give.attr = FALSE)
## spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ id          : num [1:8322] 1147 1169 1350 5992 1212 ...
##  $ zona        : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ piso        : chr [1:8322] NA NA NA "02" ...
##  $ estrato     : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
##  $ preciom     : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
##  $ areaconst   : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
##  $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
##  $ banios      : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
##  $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
##  $ tipo        : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
##  $ barrio      : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
##  $ longitud    : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
##  $ latitud     : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...

Medidas de dispersión y centralidad

Se identifica que hay inmubles con 0 habitaciones o 0 baños, lo cual no es común en la realidad.

descr(vivienda, 
      stats = c("mean", "med", "sd", "min", "q1", "q3", "max", "IQR", "cv"), 
      transpose = TRUE)
## Descriptive Statistics  
## vivienda  
## N: 8322  
## 
##                         Mean    Median   Std.Dev      Min        Q1        Q3       Max       IQR     CV
## ------------------ --------- --------- --------- -------- --------- --------- --------- --------- ------
##          areaconst    174.93    123.00    142.96    30.00     80.00    229.00   1745.00    149.00   0.82
##             banios      3.11      3.00      1.43     0.00      2.00      4.00     10.00      2.00   0.46
##            estrato      4.63      5.00      1.03     3.00      4.00      5.00      6.00      1.00   0.22
##       habitaciones      3.61      3.00      1.46     0.00      3.00      4.00     10.00      1.00   0.40
##                 id   4160.00   4160.00   2401.63     1.00   2080.00   6240.00   8319.00   4159.00   0.58
##            latitud      3.42      3.42      0.04     3.33      3.38      3.45      3.50      0.07   0.01
##           longitud    -76.53    -76.53      0.02   -76.59    -76.54    -76.52    -76.46      0.02   0.00
##       parqueaderos      1.84      2.00      1.12     1.00      1.00      2.00     10.00      1.00   0.61
##            preciom    433.89    330.00    328.65    58.00    220.00    540.00   1999.00    320.00   0.76

Matriz de correlación de los atributos

No se identifican atributos redundantes. La relación fuerte es de los atributos ID y Longitud (-0.96).

# Filtrar solo columnas numéricas
vivienda_num <- vivienda[, sapply(vivienda, is.numeric)]

matriz_cor <- cor(vivienda_num, use = "complete.obs")

#Graficar
corrplot(matriz_cor,
         method = "color",
         type = "full",
         col = colorRampPalette(c("blue", "white", "red"))(200),
         addCoef.col = "black",
         number.cex = 0.5,
         tl.col = "black",
         tl.srt = 45,
         diag = TRUE)

Datos faltantes por atributo

Se identifica que la varibales piso y parqueaderos tiene un alto porcentaje de datos NA

data.frame(
  NAN = colSums(is.na(vivienda)),
  Percent = round(colSums(is.na(vivienda)) / nrow(vivienda) * 100, 2)
)
##               NAN Percent
## id              3    0.04
## zona            3    0.04
## piso         2638   31.70
## estrato         3    0.04
## preciom         2    0.02
## areaconst       3    0.04
## parqueaderos 1605   19.29
## banios          3    0.04
## habitaciones    3    0.04
## tipo            3    0.04
## barrio          3    0.04
## longitud        3    0.04
## latitud         3    0.04

Valores atípicos de atributos numéricos

Los boxplots muestran una alta dispersión y presencia de valores atípicos en las variables precio y área construida, lo cual es totalmente factible y esperado en el mercado inmobiliario. Los inmuebles no son bienes homogéneo.

par(mar = c(8,4,4,2)) 

boxplot(vivienda_num,
        las = 2,
        main = "Boxplots de atributos numéricos",
        col = "blue",
        ylim = c(0, 2000))

Resgistros duplicados en el conjunto de datos

sum(duplicated(vivienda))
## [1] 1

2. Preparación de los datos

Se elimina el atributo Id, ya que no será relevante para los análisis posteriores y se convierte el atributo estrato en factor

vivienda$id <- NULL

vivienda$estrato <- as.factor(vivienda$estrato)

Se remplazan con la mediana los valores en 0 de los atributos banios y habitaciones, no es comun encontrar inmubles sin estas característica. En ambos casos la mediana de los atributos es equivalente a 3.

vivienda$habitaciones[vivienda$habitaciones == 0] <- 3

vivienda$banios[vivienda$banios == 0] <- 3   

Los atributos numéricos con datos faltantes se remplazan con la mediana, los atributos categóricos con datos faltantes se remplazan con la moda

# Identificar columnas categóricas y numéricas
categoricas <- c("piso", "zona", "tipo","barrio", "estrato")
numericas   <- sapply(vivienda, is.numeric)

# Función para calcular la moda
moda <- function(x) {
  ux <- unique(x[!is.na(x) & x != ""])
  ux[which.max(tabulate(match(x, ux)))]
}

# Reemplazar NA en columnas categóricas por la moda
vivienda[categoricas] <- lapply(vivienda[categoricas], function(x) {
  moda_valor <- moda(x)
  x[is.na(x) | x == ""] <- moda_valor
  return(x)
})

# Reemplazar NA en columnas numéricas por la mediana
vivienda[numericas] <- lapply(vivienda[numericas], function(x) {
  x[is.na(x)] <- median(x, na.rm = TRUE)
  return(x)
})


data.frame(
  NAN = colSums(is.na(vivienda))
)
##              NAN
## zona           0
## piso           0
## estrato        0
## preciom        0
## areaconst      0
## parqueaderos   0
## banios         0
## habitaciones   0
## tipo           0
## barrio         0
## longitud       0
## latitud        0

Los valores atípicos identificados en los atributos preciom, areaconst, banios, parqueaderos y habitaciones son estadísticamente extremos; sin embargo, son plausibles en la realidad, considerando el tipo y las características de las viviendas. Por esta razón, no se procedió a imputarlos ni a eliminarlos.

Finalmente se eliminan registros duplicados

vivienda <- vivienda[!duplicated(vivienda), ]

sum(duplicated(vivienda))
## [1] 0

3. Análisis

a. Componentes principales (PCA)

vivienda_n <- vivienda[, sapply(vivienda, is.numeric)]# Atributos numéricos normalizados

viviendaZ = scale(vivienda_n)     # datos estandarizados

summary(vivienda_n)
##     preciom         areaconst       parqueaderos        banios     
##  Min.   :  58.0   Min.   :  30.0   Min.   : 1.000   Min.   : 1.00  
##  1st Qu.: 220.0   1st Qu.:  80.0   1st Qu.: 1.000   1st Qu.: 2.00  
##  Median : 330.0   Median : 123.0   Median : 2.000   Median : 3.00  
##  Mean   : 434.7   Mean   : 175.2   Mean   : 1.869   Mean   : 3.13  
##  3rd Qu.: 548.0   3rd Qu.: 229.0   3rd Qu.: 2.000   3rd Qu.: 4.00  
##  Max.   :1999.0   Max.   :1745.0   Max.   :10.000   Max.   :10.00  
##   habitaciones      longitud         latitud     
##  Min.   : 1.00   Min.   :-76.59   Min.   :3.333  
##  1st Qu.: 3.00   1st Qu.:-76.54   1st Qu.:3.381  
##  Median : 3.00   Median :-76.53   Median :3.416  
##  Mean   : 3.63   Mean   :-76.53   Mean   :3.418  
##  3rd Qu.: 4.00   3rd Qu.:-76.52   3rd Qu.:3.452  
##  Max.   :10.00   Max.   :-76.46   Max.   :3.498
summary(viviendaZ)
##     preciom          areaconst        parqueaderos         banios        
##  Min.   :-1.1434   Min.   :-1.0140   Min.   :-0.8570   Min.   :-1.50912  
##  1st Qu.:-0.6517   1st Qu.:-0.6647   1st Qu.:-0.8570   1st Qu.:-0.80045  
##  Median :-0.3178   Median :-0.3643   Median : 0.1292   Median :-0.09179  
##  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.00000  
##  3rd Qu.: 0.3440   3rd Qu.: 0.3762   3rd Qu.: 0.1292   3rd Qu.: 0.61688  
##  Max.   : 4.7485   Max.   :10.9665   Max.   : 8.0181   Max.   : 4.86887  
##   habitaciones        longitud           latitud        
##  Min.   :-1.8453   Min.   :-3.47449   Min.   :-1.98482  
##  1st Qu.:-0.4422   1st Qu.:-0.74487   1st Qu.:-0.86381  
##  Median :-0.4422   Median :-0.07897   Median :-0.03829  
##  Mean   : 0.0000   Mean   : 0.00000   Mean   : 0.00000  
##  3rd Qu.: 0.2594   3rd Qu.: 0.55880   3rd Qu.: 0.80599  
##  Max.   : 4.4686   Max.   : 3.76718   Max.   : 1.87775

Con el fin de evitar que las variables que tiene una escala con valores más grandes afecten las estimaciones realizadas (sesgos) se realiza la estandarización de las variables antes de proceder a realizar el proceso de estimación de los componentes principales.

viviendaZ= scale(vivienda_n[,2:5])
head(viviendaZ) # primeros 6 registros  
##       areaconst parqueaderos      banios habitaciones
## [1,] -0.7345723   -0.8569549 -0.09178938    1.6624437
## [2,] -0.3852873   -0.8569549 -0.80045486   -0.4421917
## [3,]  0.3132828    0.1291580 -0.80045486    0.2593534
## [4,]  0.7324249    1.1152709  1.32554158   -0.4421917
## [5,] -0.5948583   -0.8569549 -0.80045486   -0.4421917
## [6,] -0.6158154   -0.8569549 -0.09178938   -0.4421917
prcomp(viviendaZ)
## Standard deviations (1, .., p=4):
## [1] 1.5968921 0.8720216 0.6024832 0.5714261
## 
## Rotation (n x k) = (4 x 4):
##                    PC1         PC2        PC3         PC4
## areaconst    0.5439284  0.03875384 -0.6407693  0.54042085
## parqueaderos 0.4310069  0.76228613  0.4767174  0.07676883
## banios       0.5480971 -0.09334458 -0.2170749 -0.80234334
## habitaciones 0.4668667 -0.63930024  0.5612786  0.24144774

Elección del número de componentes principales

En este caso el primer componente principal explica el 63.8% de la variabilidad contenida en la base de datos y entre los dos primeros se casi el 80% de los datos (82.8), lo cual indicaría que con solo una variable (CP1) que se obtiene mediante una combinación lineal de las variables se puede resumir gran parte de la variabilidad que contiene la base de datos.

viviendaZ= scale(vivienda_n[,2:5]) 
res.pca <- prcomp(viviendaZ)
fviz_eig(res.pca, addlabels = TRUE)

El gráfico de variables del PCA muestra que la Dim1 (63.8%) está fuertemente explicada de manera conjunta por área construida, baños y habitaciones, ya que sus vectores apuntan en la misma dirección y con alta correlación positiva, lo que confirma que el tamaño del inmueble y su nivel de dotación estructural son el principal factor de diferenciación del mercado. Por su parte, parqueaderos también contribuye de forma importante, pero se orienta más hacia la Dim2 (19%), lo que indica que esta variable introduce una diferenciación adicional independiente del tamaño tradicional del inmueble. En términos estratégicos, lo más relevante es que el mercado se segmenta principalmente por escala (área y número de espacios internos), mientras que la disponibilidad de parqueaderos funciona como un factor complementario que puede marcar distinción competitiva en ciertos segmentos.

fviz_pca_var(res.pca,
col.var = "contrib", # Color by contributions to the PC
gradient.cols = c("#FF7F00",  "#034D94"),
repel = TRUE     # Avoid text overlapping
)

Para explicar el sentido de los ejes, se escogen cuatro casos extremos conformados por los siguientes clientes:

Extremo positivo en Dim1 = inmueble más grande (registro 3131)

Extremo negativo en Dim1 = inmueble más pequeño (registro 8133)

Extremo positivo en Dim2 = inmueble con muchos parqueaderos respecto al resto (registro 1751)

Extremo negativo en Dim2 = nmueble con más habitaciones (registro 279)

# vivienda_n[which.max(vivienda_n$areaconst), identifica el registro del valor extremo

datos<- rbind(vivienda_n[3131,], # ok
vivienda_n[8133,],
vivienda_n[1751,],
vivienda_n[279,])

datos <- as.data.frame(datos)
rownames(datos) = c("Inmueble 3131","Inmueble 8133","Inmueble 1751","Inmueble 279")

datos[, c("areaconst", "parqueaderos", "banios", "habitaciones")]
##               areaconst parqueaderos banios habitaciones
## Inmueble 3131      1745            2      3            2
## Inmueble 8133        30            1      2            3
## Inmueble 1751      1586           10      4            5
## Inmueble 279        750            2      8           10

El gráfico del PCA muestra que la mayor parte de la variabilidad de los inmuebles (82.8%) se explica en dos dimensiones, donde la primera (63.8%) está asociada principalmente al tamaño y nivel del inmueble (mayor área, más baños, habitaciones y parqueaderos), convirtiéndose en el eje que más diferencia el mercado. La mayoría de las propiedades se concentran en una zona central, lo que indica un mercado relativamente homogéneo y dominado por inmuebles de características medias; sin embargo, se observan algunos puntos claramente alejados que representan propiedades atípicas, específicamente los inmuebles 1751, 279, 3131 y 8133, los cuales se diferencian por tener áreas muy grandes, un número inusual de habitaciones o parqueaderos, o tamaños extremadamente pequeños. En conjunto, el gráfico evidencia que el tamaño es el principal factor de diferenciación y que existen pocos inmuebles que se apartan significativamente del patrón general.

casos1 <- rbind(res.pca$x[3131,1:2],res.pca$x[8133,1:2]) # CP1
rownames(casos1) = c("3131","8133")
casos1 <- as.data.frame(casos1)

casos2 <- rbind(res.pca$x[1751,1:2], res.pca$x[279,1:2]) # CP2
rownames(casos2) = c("1751","279")
casos2 <- as.data.frame(casos2)

fviz_pca_ind(res.pca, col.ind = "#DEDEDE", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07")) +
geom_point(data = casos1, aes(x = PC1, y = PC2), color = "red", size = 3) +
geom_point(data = casos2, aes(x = PC1, y = PC2), color = "blue", size = 3)

El biplot muestra que la Dim1 (63.8%) está asociada principalmente con área construida, habitaciones y baños, variables fuertemente correlacionadas entre sí y que representan el tamaño del inmueble. En esta dimensión, las Casas tienden a ubicarse hacia valores más altos, indicando mayores áreas y más espacios, mientras que los Apartamentos se concentran más cerca del origen o en valores menores. La variable parqueaderos también se relaciona positivamente con el tamaño, diferenciando especialmente a las Casas en la Dim2 (19%). La cercanía angular entre las flechas confirma la correlación positiva entre todas las variables estructurales. En conjunto, las Casas muestran mayor variabilidad y asociación con inmuebles de mayor tamaño, mientras que los Apartamentos presentan características más compactas y homogéneas.

library(factoextra)
fviz_pca_biplot(res.pca, 
repel = TRUE,
habillage = vivienda$tipo,
col.var = "#034A94", # Variables color
col.ind = c("#DEDEDE", "#034A94")  # Individuals color
)

b. Conglomerados

Dado que el dataset contiene más de 8.000 registros, se tomó una muestra representativa de 400 observaciones con el fin de optimizar el rendimiento computacional y reducir los tiempos de procesamiento durante la ejecución de los análisis. Esta decisión facilita una renderización más ágil del archivo RMarkdown.

set.seed(1234)
vivienda_sample <- sample_n(vivienda_n, 400)  # selecciona una muestra del dataset

rownames(vivienda_sample) <- paste0("E", 1:nrow(vivienda_sample))

viv_z <- scale(vivienda_sample)
viv_z <- as.data.frame(viv_z)
viv_z[1:5, ]
##       preciom  areaconst parqueaderos      banios habitaciones  longitud
## E1 -0.7297508 -0.6565838   -0.7168618 -0.78509171   -0.3933114 0.5253162
## E2 -0.8569308 -0.4584833    0.1314954 -0.78509171   -0.3933114 2.4131477
## E3 -0.8251358 -0.7688408   -0.7168618 -0.78509171   -1.1878799 0.4270471
## E4 -0.6820583 -0.4584833   -0.7168618 -0.01727586    0.4012571 1.4659761
## E5 -0.4753908 -0.5773436   -0.7168618 -0.01727586   -0.3933114 0.3187144
##       latitud
## E1 -1.1394168
## E2  1.0383504
## E3 -1.1494991
## E4 -0.4622644
## E5 -1.3028432

Las distancias correspondientes a los valores estandarizados serán:

Distancias euclidianas

dist(viv_z, method = "euclidean")

Distamcias de Manhattan

dist(viv_z, method = "manhattan")

Distancias de Minkowski

dist(viv_z, method = "minkowski")

Distribución de los individuos por distancias

El gráfico de distribución por distancias segmenta los 400 inmuebles en cuatro clústeres diferenciados principalmente por área construida y precio. El clúster 1 (rojo) concentra la oferta masiva de propiedades pequeñas y económicas, mientras que el clúster 2 (verde) representa un segmento medio con mayor variabilidad de precios. Los clústeres 3 (azul) y 4 (morado) identifican claramente a los valores atípicos o outliers, como el Cliente 1751, que se alejan del grupo principal debido a dimensiones y costos excepcionalmente altos. En conclusión, la visualización confirma que la mayoría del mercado es homogénea, con apenas un puñado de propiedades rompiendo la tendencia hacia el extremo superior del gráfico.

# distancia euclidiana
dist_emp <- dist(viv_z, method = 'euclidean')

# Clúster jerárquico con el método complete
hc_emp <- hclust(dist_emp, method = 'complete')

# Determinamos a dónde pertenece cada observación
cluster_assigments <- cutree(hc_emp, k = 4)

# asignamos los clusters
assigned_cluster <- viv_z %>% mutate(cluster = as.factor(cluster_assigments))


# gráfico de puntos
ggplot(assigned_cluster, aes(x = areaconst, y = preciom, color = cluster)) +
geom_point(size = 4) +
geom_text(aes(label = cluster), vjust = -.8) + # Agregar etiquetas del clúster
theme_classic()

El dendrograma muestra la jerarquía de agrupación de los 400 inmuebles, donde la Distancia Euclidiana en el eje vertical revela una clara separación del mercado en dos segmentos principales. El primer grupo (recuadro rojo) es un segmento minoritario de “atípicos” que se desprende prematuramente del resto debido a características extremas, como las observadas en el Cliente 1751 (gran área y 10 parqueaderos). El segundo grupo (recuadro verde) concentra a la gran mayoría de los registros, quienes presentan una alta densidad en la base (entre distancia 0 y 3), lo que indica una oferta inmobiliaria muy homogénea con variaciones mínimas en su configuración estructural. Esta estructura sugiere que, para fines prácticos, el mercado se divide entre una masa estándar masiva y un nicho exclusivo de propiedades con dimensiones fuera de la norma.

plot(hc_emp, cex = 0.6, main = "Dendograma de Empresas", las=1,
ylab = "Distancia euclidiana", xlab = "Grupos")
rect.hclust(hc_emp, k = 2, border = 2:5)

Clasificación de los inmuebles

dendograma <- hclust(dist_emp, method = "average")
grp <- cutree(dendograma, k = 4)
grp

Elección del número de conglomerados

El gráfico de Agregaciones, basado en las distancias euclidianas, visualiza la progresión del agrupamiento jerárquico de tus datos. Su forma descendente muestra cómo se reducen drásticamente los nodos al inicio, lo que indica que la gran mayoría de los 400 inmuebles son muy similares entre sí y se agrupan rápidamente. La estabilización de la curva hacia la derecha representa a los elementos “atípicos” o outliers, que requieren un “peso” o distancia mucho mayor para ser integrados al grupo principal.

dist_emp <- dist(viv_z, method = "euclidean")
dendograma <- hclust(dist_emp, method = "average")
# plot(dendograma, cex = 0.6, hang = -1) 
barplot(sort(dendograma$height, decreasing = TRUE), horiz = TRUE, 
main = "Agregaciones (distancias euclidianas)",
col = "lightblue", ylab = "Nodo", xlab = "Peso", xlim = c(0, 2.5))

Un coeficiente de Silhouette promedio de 0.3948 para k = 4 indica que la segmentación de los inmuebles presenta una estructura moderada pero no claramente definida, lo que significa que, aunque los inmuebles tienden a estar más próximos a los de su propio conglomerado que a los de otros grupos, existe cierto solapamiento entre clusters. En términos prácticos, los cuatro conglomerados logran diferenciar parcialmente perfiles de inmuebles (por ejemplo, por precio, tamaño o ubicación), pero las fronteras entre ellos no son muy nítidas, lo que sugiere heterogeneidad interna o características compartidas entre grupos.

library(cluster)
# distancia euclidiana
dist_emp <- dist(viv_z, method = 'euclidean')

# Clúster jerárquico con el método complete
hc_emp <- hclust(dist_emp, method = 'complete')

# Determinamos a dónde pertenece cada observación
cluster_assigments <- cutree(hc_emp, k = 4)

# Calcular el coeficiente de Silhouette
sil <- silhouette(cluster_assigments, dist(viv_z))
sil_avg <- mean(sil[,3])

# Imprimir el coeficiente de Silhouette promedio
cat("Coeficiente de Silhouette promedio k=4 : ", sil_avg)
## Coeficiente de Silhouette promedio k=4 :  0.3948325

c. Correspondencia

tabla <- table(vivienda$zona, vivienda$estrato)
colnames(tabla) <- c("Estrato3", "Estrato4", "Estrato5", "Estrato6" )
tabla
##               
##                Estrato3 Estrato4 Estrato5 Estrato6
##   Zona Centro       105       14        4        1
##   Zona Norte        567      406      763      172
##   Zona Oeste         54       83      289      769
##   Zona Oriente      339        8        2        1
##   Zona Sur          380     1594     1670     1040

El resultado del test Chi-cuadrado muestra un estadístico X² = 3802.6 con 12 grados de libertad (df = 12) y un p-valor < 2.2e-16, lo que evidencia una diferencia grande entre las frecuencias observadas y las esperadas bajo el supuesto de independencia. Dado que el p-valor es menor al nivel de significancia convencional (α = 0.05), se rechaza la hipótesis nula de independencia, concluyendo que existe una asociación estadísticamente significativa entre las variables.

chisq.test(tabla)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla
## X-squared = 3802.6, df = 12, p-value < 2.2e-16

El mapa factorial de Análisis de Correspondencias muestra que la Dimensión 1 (70.03%) explica la mayor parte de la variabilidad, diferenciando principalmente las zonas y los estratos socioeconómicos. Se observa una fuerte asociación entre Zona Oriente y Estrato 3, así como entre Zona Centro y posiciones intermedias positivas en la Dim 1. En contraste, Zona Oeste se relaciona más con Estrato 6, mientras que Zona Sur se aproxima a Estratos 4 y 5, indicando perfiles similares. La cercanía entre puntos sugiere mayor asociación, mientras que la lejanía respecto al origen indica mayor contribución a la explicación de la relación entre variables.

resultados_ac <- CA(tabla)

valores_prop <-resultados_ac$eig ; valores_prop
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.32236431              70.032960                          70.03296
## dim 2 0.12732444              27.660964                          97.69392
## dim 3 0.01061495               2.306076                         100.00000

El clustering con k = 4 muestra una calidad moderada (Silhouette = 0.3948), indicando separación aceptable pero no óptima entre grupos.El análisis factorial revela que Dim 1 (70.03%) y Dim 2 (27.66%) explican el 97.69% de la variabilidad, por lo que la estructura se interpreta casi totalmente en dos dimensiones.

fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")

Conclusión

El análisis evidencia que el 82.8% de la variabilidad del mercado se explica en dos dimensiones del PCA, donde la Dim1 (63.8%) está determinada por área construida, habitaciones, baños y parqueaderos, confirmando cuantitativamente que el tamaño es el principal factor de diferenciación. El biplot muestra que las Casas se ubican en los valores más altos de esta dimensión, asociándose a mayores áreas y más parqueaderos, lo que estructuralmente las posiciona en segmentos de mayor valor (inmuebles de mayor tamaño y dotación estructural). En contraste, los Apartamentos se concentran cerca del origen o en valores intermedios y bajos de la Dim1, lo que indica menor área y menor número de espacios, reflejando un producto más estandarizado y homogéneo.

La segmentación en 4 clústeres refuerza esta estructura: el clúster 1 concentra principalmente esta oferta masiva de apartamentos pequeños, caracterizados por menor dispersión en precio y tamaño, mientras que los clústeres 3 y 4 agrupan inmuebles atípicos de gran tamaño y precio elevado, como el 1751, evidenciando un segmento reducido pero diferenciado. Además, el Análisis de correspondencias indica que la Dim1 explica el 70.03% de la relación entre zona y estrato, mostrando asociación directa entre Zona Oeste y Estrato 6, y entre Zona Sur y Estratos 4 y 5, es decir, áreas con mayor nivel socioeconómico. En este contexto, los apartamentos ubicados en estas zonas pueden representar una estrategia de inversión intermedia atractiva: aunque estructuralmente son más compactos, su localización en estratos altos puede incrementar su valor relativo. Por tanto, la recomendación es focalizar inversión en zonas de estratos 5 y 6, priorizando Casas para maximizar margen y Apartamentos bien ubicados para asegurar rotación y liquidez.

4. Anexos

Se incluye el código en el documento Rmd como anexo bajo las opciones Show all code - Hide all code