1. Introducción

El presente informe tiene como objetivo realizar un análisis multidimensional del mercado inmobiliario urbano a partir de una base de datos de 8,322 propiedades residenciales obtenidas mediante webscraping de la plataforma OLX. Se aplicarán técnicas de Análisis de Componentes Principales (PCA), Análisis de Conglomerados y Análisis de Correspondencia para identificar patrones, segmentaciones y relaciones entre las variables del mercado.

#Instalamos los paquetes que necesitamos 

options(repos = c(CRAN = "https://cloud.r-project.org"))
install.packages("factoextra")
## Installing package into 'C:/Users/ASUS/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'factoextra' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\ASUS\AppData\Local\Temp\Rtmpsdk3SF\downloaded_packages
install.packages("cluster")
## Installing package into 'C:/Users/ASUS/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'cluster' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'cluster'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problema al copiar
## C:\Users\ASUS\AppData\Local\R\win-library\4.5\00LOCK\cluster\libs\x64\cluster.dll
## a C:\Users\ASUS\AppData\Local\R\win-library\4.5\cluster\libs\x64\cluster.dll:
## Permission denied
## Warning: restored 'cluster'
## 
## The downloaded binary packages are in
##  C:\Users\ASUS\AppData\Local\Temp\Rtmpsdk3SF\downloaded_packages
install.packages("ggplot2")
## Installing package into 'C:/Users/ASUS/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'ggplot2' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\ASUS\AppData\Local\Temp\Rtmpsdk3SF\downloaded_packages
install.packages("devtools")
## Installing package into 'C:/Users/ASUS/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## also installing the dependency 'cli'
## package 'cli' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'cli'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problema al copiar
## C:\Users\ASUS\AppData\Local\R\win-library\4.5\00LOCK\cli\libs\x64\cli.dll a
## C:\Users\ASUS\AppData\Local\R\win-library\4.5\cli\libs\x64\cli.dll: Permission
## denied
## Warning: restored 'cli'
## package 'devtools' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\ASUS\AppData\Local\Temp\Rtmpsdk3SF\downloaded_packages

2. Carga y preparación de datos:

#Intalamos las librerias 
library(paqueteMODELOS)
## Cargando paquete requerido: boot
## Cargando paquete requerido: broom
## Warning: package 'broom' was built under R version 4.5.3
## Cargando paquete requerido: GGally
## Warning: package 'GGally' was built under R version 4.5.3
## Cargando paquete requerido: ggplot2
## Warning: package 'ggplot2' was built under R version 4.5.3
## Cargando paquete requerido: gridExtra
## Warning: package 'gridExtra' was built under R version 4.5.3
## Cargando paquete requerido: knitr
## Cargando paquete requerido: summarytools
library(FactoMineR)
## Warning: package 'FactoMineR' was built under R version 4.5.3
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.5.3
## Welcome to factoextra!
## Want to learn more? See two factoextra-related books at https://www.datanovia.com/library/principal-component-methods
library(cluster)
## Warning: package 'cluster' was built under R version 4.5.3
library(ggplot2)

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

Una vez cargada la información, se debe realizar una limpieza inicial, donde se eliminan los valores nulos, celdas vacías y demás elementos que puedan afectar el análisis del conjunto de datos.

# Limpieza: seleccionar variables numéricas y eliminar NA
vivienda_limpia <- vivienda %>%
  dplyr::select(estrato, preciom, areaconst, 
                parqueaderos, banios, habitaciones) %>%
  na.omit()

# Resumen estadístico
summary(vivienda_limpia)
##     estrato        preciom         areaconst       parqueaderos   
##  Min.   :3.00   Min.   :  58.0   Min.   :  30.0   Min.   : 1.000  
##  1st Qu.:4.00   1st Qu.: 248.0   1st Qu.:  86.0   1st Qu.: 1.000  
##  Median :5.00   Median : 355.0   Median : 130.0   Median : 2.000  
##  Mean   :4.83   Mean   : 468.9   Mean   : 181.1   Mean   : 1.835  
##  3rd Qu.:6.00   3rd Qu.: 580.0   3rd Qu.: 233.0   3rd Qu.: 2.000  
##  Max.   :6.00   Max.   :1999.0   Max.   :1745.0   Max.   :10.000  
##      banios        habitaciones   
##  Min.   : 0.000   Min.   : 0.000  
##  1st Qu.: 2.000   1st Qu.: 3.000  
##  Median : 3.000   Median : 3.000  
##  Mean   : 3.255   Mean   : 3.611  
##  3rd Qu.: 4.000   3rd Qu.: 4.000  
##  Max.   :10.000   Max.   :10.000

2.1 Análisis Descriptivo

QUITAR LA MEDIA DEL ESTRATO PRUEBA DE ESFERICIDAD DE cortest.bartlett()

El resumen estadístico de las variables numéricas revela las siguientes

características del mercado inmobiliario:

  • Estrato: Las propiedades se concentran entre estratos 4 y 6 (media = 4.83), lo que indica que la oferta disponible en OLX corresponde principalmente a viviendas de estratos medios y altos.

  • Precio: El precio promedio es de 468.9 millones de pesos, con una mediana de 355 millones, lo que sugiere una distribución asimétrica hacia precios altos. El rango va desde 58 hasta 1,999 millones.

  • Área construida: El promedio es de 181 m², con un mínimo de 30 m² y un máximo de 1,745 m², reflejando gran variedad en el tamaño de las propiedades.

  • Parqueaderos: La mayoría de propiedades tiene entre 1 y 2 parqueaderos (media = 1.83).

  • Baños y habitaciones: En promedio las propiedades tienen 3 baños y 3.6 habitaciones.

3. Análisis de Componentes Principales (PCA)

El Análisis de Componentes Principales permite reducir la dimensionalidad del conjunto de datos, identificando las combinaciones lineales de variables que explican la mayor varianza posible. Esto facilita visualizar la estructura de los datos y entender qué variables influyen más en la variación del mercado.

# Estandarizar los datos (importante para PCA)
vivienda_scaled <- scale(vivienda_limpia)

# Aplicar PCA
pca_result <- PCA(vivienda_limpia, scale.unit = TRUE, graph = FALSE)

# Ver varianza explicada por cada componente
print(pca_result$eig)
##        eigenvalue percentage of variance cumulative percentage of variance
## comp 1  3.4837687              58.062812                          58.06281
## comp 2  1.2230753              20.384588                          78.44740
## comp 3  0.4994925               8.324875                          86.77227
## comp 4  0.3595346               5.992243                          92.76452
## comp 5  0.2443838               4.073063                          96.83758
# Gráfico de varianza explicada (scree plot)
fviz_eig(pca_result, addlabels = TRUE, ylim = c(0, 60),
         title = "Gráfico 1. Varianza explicada por cada componente principal")
## Warning: This FactoMineR PCA result contains only 5 eigenvalues and does not
## include the complete spectrum. Refit the PCA with a larger `ncp` before drawing
## a complete scree plot.

3.1 Resultados del PCA

La tabla de valores propios (eigenvalues) muestra que:

  • Componente 1 explica el 58.06% de la varianza total, siendo el más importante. Captura la mayor parte de la información del mercado.

  • Componente 2 explica el 20.38% adicional de varianza.

  • Entre los dos primeros componentes se explica el 78.45% de la varianza total, lo que indica que una representación bidimensional es suficiente para capturar la estructura principal de los datos.

  • Siguiendo el criterio de Kaiser (eigenvalue > 1), se retienen los 2 primeros componentes para el análisis.

El scree plot confirma este resultado, mostrando un codo pronunciado después del segundo componente.

3.2 Contribución de las variables al PCA

Este paso es muy importante para comprender cuáles son los factores que realmente impulsan la variación en el mercado inmobiliario, ya que no todas las variables tienen el mismo peso en la construcción de los componentes principales.

# Gráfico de contribución de variables (círculo de correlación)
fviz_pca_var(pca_result,
             col.var = "contrib",
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
             repel = TRUE,
             title = "Gráfico 2. Variables en el plano de componentes principales")

# Ver contribución de cada variable
print(pca_result$var$contrib)
##                  Dim.1     Dim.2     Dim.3      Dim.4     Dim.5
## estrato       8.726010 40.671280 29.496074  0.5004944 18.917625
## preciom      22.135031  5.734831  1.168642  8.4681556  7.072094
## areaconst    20.274526  4.177985  6.732603 43.1926934  9.231817
## parqueaderos 18.301372  2.289306 37.969100 38.4959739  1.421827
## banios       21.646246  2.556712 13.657047  1.9812007 46.005744
## habitaciones  8.916814 44.569885 10.976533  7.3614820 17.350893

Interpretación de los resultados:

Dimensión 1 (58.1%) - “Tamaño y valor de la propiedad”: Las variables que más contribuyen a esta dimensión son: - preciom (22.1%): el precio es el factor más determinante - banios (21.6%): número de baños - areaconst (20.3%): área construida - parqueaderos (18.3%): número de parqueaderos

Todas apuntan en la misma dirección (positiva), lo que indica que propiedades más grandes tienden a ser más caras y tener más baños y parqueaderos. Esta dimensión puede interpretarse como el “tamaño y valor de la propiedad”.

Dimensión 2 (20.4%) - “Distribución interna”: Las variables que más contribuyen son: - habitaciones (44.6%): número de habitaciones - estrato (40.7%): estrato socioeconómico

Esto sugiere que la segunda dimensión captura la relación entre el estrato y la distribución interna de la vivienda. Propiedades con más habitaciones no necesariamente son de estrato alto.

3.3 Analisis de propiedades en el plano principal

En este caso la representación de las propiedades en el plano principal del PCA es muy útil, debido a que se puede ver mejor el comportamiento de las multiples variables en simultáneo, en este caso el precio, área, estrato, baños, habitaciones, parqueaderos.

También, se pueden identificación de patrones, pues al proyectar las 8,322 propiedades en el plano principal, es posible identificar visualmente grupos de viviendas con características similares.

Detección de valores atípicos: Las propiedades que aparecen alejadas del centro del plano representan casos inusuales, como viviendas con precios o áreas extremadamente altos. Identificar estos outliers es crucial para evitar distorsiones en la valoración de propiedades.

# Biplot combinando variables e individuos
fviz_pca_biplot(pca_result,
                col.ind = as.factor(vivienda_limpia$estrato),
                palette = c("#00AFBB", "#E7B800", "#FC4E07", 
                           "#7CAE00", "#C77CFF"),
                addEllipses = TRUE,
                col.var = "black",
                legend.title = "Estrato",
                title = "Gráfico 3. Biplot PCA - Viviendas por estrato")

Con este gráfico se pueden identificar algunos patrones importantes, pero es importante tener en cuenta que el Dim1 representa el precio, área construida y baños en base al estrato. Algunos patrones son:

  • Existe una clara separación entre estratos, especialmente entre el estrato 3 y los estratos 5-6, lo que confirma que el estrato socioeconómico es un diferenciador clave del mercado.

  • Las viviendas de estrato 6 se concentran hacia la derecha del eje Dim1, asociadas con mayores valores de precio, área construida, baños y parqueaderos.

  • Las viviendas de estrato 3 se ubican hacia la izquierda, correspondiendo a propiedades de menor precio y tamaño.

  • Los estratos 4 y 5 ocupan posiciones intermedias, mostrando una progresión clara entre estrato y características de la vivienda.

  • La superposición de las elipses indica que existe cierta variabilidad dentro de cada estrato, especialmente en los estratos 4 y 5.

  • Las variables preciom, areaconst y banios apuntan hacia las viviendas de estrato alto, confirmando su correlación positiva con el valor de la propiedad.

4. Análisis de Conglomerados (Clustering)

El análisis de conglomerados busca agrupar las propiedades en segmentos homogéneos con características similares, permitiendo identificar perfiles de vivienda en el mercado. Se utilizará el método K-means, que agrupa los datos minimizando la varianza dentro de cada grupo.

Para determinar el número óptimo de grupos se utilizará el método del codo.

# Estandarizar datos
vivienda_scaled <- scale(vivienda_limpia)

# Método del codo para determinar número óptimo de clusters
set.seed(123)
fviz_nbclust(vivienda_scaled, kmeans, method = "wss", k.max = 10) +
  labs(title = "Gráfico 4. Método del codo para número óptimo de clusters")

El método del codo muestra la reducción de la varianza interna (Within Sum of Squares) a medida que aumenta el número de clusters. Se busca el punto donde la curva comienza a aplanarse, formando un “codo”.

En este caso, el codo se observa en k = 4 clusters, punto a partir del cual agregar más grupos no reduce significativamente la varianza interna. Por lo tanto, se seleccionan 4 conglomerados para el análisis.

4.2 Aplicación del algoritmo K-means

El algoritmo K-means resulta fundamental en el análisis del ejercicio ya que, permite segmentar las propiedades considerando simultáneamente múltiples, en este caso, variables como precio, área construida, número de baños, parqueaderos y habitaciones, generando grupos más precisos y representativos de la realidad del mercado.

En este caso, los 4 clusters identificados permiten observar nichos entre las viviendas económicas hasta propiedades de lujo premium, información que permite enfocar sus estrategias comerciales en los segmentos más rentables. Asimismo, conocer el cluster al que pertenece una propiedad facilita su valoración y comparación con otros inmuebles similares, lo cual permite saber si está sobrevalorada o subvalorada en el mercado.

Por último, el K-means tiene una gran escalabilidad, pues puede processar grandes volúmenes de datos eficientemente y ejecutarse periódicamente.

# Aplicar K-means con 4 clusters
set.seed(123)
kmeans_result <- kmeans(vivienda_scaled, centers = 4, nstart = 25)

# Visualizar los clusters en el plano principal
fviz_cluster(kmeans_result, data = vivienda_scaled,
             geom = "point",
             ellipse.type = "convex",
             palette = c("#00AFBB", "#E7B800", "#FC4E07", "#7CAE00"),
             ggtheme = theme_minimal()) +
  labs(title = "Gráfico 5. Clusters de viviendas en el plano principal")

# Ver características promedio de cada cluster
vivienda_limpia$cluster <- kmeans_result$cluster
aggregate(vivienda_limpia[,-7], by = list(Cluster = vivienda_limpia$cluster), mean)
##   Cluster  estrato   preciom areaconst parqueaderos   banios habitaciones
## 1       1 5.551375  532.6025 170.27264     2.029908 3.576942     3.372890
## 2       2 4.112434  460.1045 298.32745     1.814815 4.458995     6.138889
## 3       3 4.273351  245.3116  95.17836     1.156760 2.222730     2.938276
## 4       4 5.743341 1145.7663 419.78981     3.880145 5.175545     4.387409

Interpretación de cada cluster:

  • Cluster 1 azul: Viviendas de estrato 5-6 con precios moderados (532M) y tamaño mediano (170 m²). Representan el segmento medio-alto más numeroso del mercado.

  • Cluster 2 amarillo: Viviendas grandes (298 m²) de estrato 4, con precios medios (460M). Son propiedades espaciosas pero en zonas de estrato medio.

  • Cluster 3 rojo: El segmento más económico, con viviendas pequeñas (95 m²), precios bajos (245M) y estrato 4. Representa la oferta más accesible del mercado.

  • Cluster 4 verde: Viviendas de lujo con el mayor precio promedio (1,146M), mayor área (420 m²), casi 4 parqueaderos y estrato 6. Son las propiedades premium del mercado.

5. Análisis de Correspondencia

El Análisis de Correspondencia examina las relaciones entre variables categóricas. Se analizará la relación entre el tipo de vivienda (Casa/Apartamento) y la zona de la ciudad, para identificar patrones de distribución de la oferta inmobiliaria.

# Crear tabla de contingencia entre tipo y zona
tabla_contingencia <- table(vivienda$tipo, vivienda$zona)
print(tabla_contingencia)
##              
##               Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
##   Apartamento          24       1198       1029           62     2787
##   Casa                100        722        169          289     1939
# Prueba chi-cuadrado para verificar asociación
chisq.test(tabla_contingencia)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla_contingencia
## X-squared = 690.93, df = 4, p-value < 2.2e-16

Prueba Chi-cuadrado: - X² = 690.93, gl = 4, p-value < 2.2e-16

El valor p extremadamente pequeño (< 0.05) indica que existe una asociación estadísticamente significativa entre el tipo de vivienda y la zona de la ciudad. Es decir, la distribución de casas y apartamentos no es aleatoria en la ciudad, sino que sigue patrones geográficos definidos.

5.2 Aplicación del Análisis de Correspondencia

El Análisis de Correspondencia es fundamental, permite examinar las relaciones entre variables categóricas como la zona geográfica y el estrato socioeconómico,

# Crear tabla zona y estrato
vivienda$estrato_cat <- paste("Estrato", vivienda$estrato)
tabla_contingencia2 <- table(vivienda$zona, vivienda$estrato_cat)
print(tabla_contingencia2)
##               
##                Estrato 3 Estrato 4 Estrato 5 Estrato 6 Estrato NA
##   Zona Centro        105        14         4         1          0
##   Zona Norte         572       407       769       172          0
##   Zona Oeste          54        84       290       770          0
##   Zona Oriente       340         8         2         1          0
##   Zona Sur           382      1616      1685      1043          0
# Análisis de Correspondencia
ca_result <- CA(tabla_contingencia2, graph = FALSE)
## Warning in CA(tabla_contingencia2, graph = FALSE): The columns Estrato NA sum
## at 0. They were suppressed from the analysis
# Ver varianza explicada
print(ca_result$eig)
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.32215213              69.965515                          69.96551
## dim 2 0.12745096              27.680002                          97.64552
## dim 3 0.01084108               2.354483                         100.00000
# Gráfico
fviz_ca_biplot(ca_result,
               repel = TRUE,
               col.row = "#FC4E07",
               col.col = "#00AFBB") +
  labs(title = "Gráfico 6. Análisis de Correspondencia - Zona por estrato")

  • Dimensión 1 explica el 70% de la varianza
  • Dimensión 2 explica el 27.7% adicional
  • Entre las dos dimensiones se explica el 97.6% de la asociación total entre zona y estrato, lo que indica una representación muy completa en el plano bidimensional.

Interpretación del gráfico:

Se puede identificar que existe una segmentación geográfica clara y significativa en la ciudad como por ejemplo:

  • Zona Oriente y Zona Centro se asocian con Estrato 3, ubicándose en el extremo derecho del gráfico. Estas zonas concentran la oferta de vivienda de estrato socioeconómico más bajo.

  • Zona Oeste se asocia fuertemente con Estrato 6, ubicándose en la parte superior izquierda. Es la zona con mayor concentración de vivienda de lujo.

  • Zona Norte se asocia principalmente con Estrato 5, representando un segmento medio-alto del mercado.

  • Zona Sur y Estrato 4 aparecen cercanos al centro del gráfico, sugiriendo una distribución más heterogénea de estratos en esta zona.

Estos resultados confirman que existe una segmentación geográfica clara del mercado inmobiliario según el estrato socioeconómico.

6. Conclusiones

El mercado inmobiliario está principalmente determinado por el tamaño y valor de las propiedades (Dim1), donde precio, área construida y número de baños son los factores más influyentes. El estrato socioeconómico actúa como diferenciador secundario.

Sobre los Conglomerados: Se identificaron 4 segmentos claros de mercado: 1. Viviendas medianas de estrato alto (segmento más numeroso) 2. Viviendas grandes de estrato medio 3. Viviendas pequeñas y económicas (segmento más accesible) 4. Viviendas de lujo premium

Sobre el Análisis de Correspondencia: Existe una segmentación geográfica definida donde la Zona Oeste concentra vivienda de lujo (estrato 6), mientras que las Zonas Oriente y Centro tienen mayor oferta de estrato 3.