Introducción

Este informe presenta un análisis detallado del mercado inmobiliario urbano con el objetivo de identificar patrones en la oferta de viviendas. Se aplican técnicas estadísticas como Análisis de Componentes Principales (ACP), Clustering y Análisis de Correspondencia.

#install.packages("FactoMineR")
#install.packages("factoextra")
#install.packages("mice")
#install.packages("naniar")
#install.packages("VIM")
#install.packages("knitr")
# Cargar librerías
library(ca)
## Warning: package 'ca' was built under R version 4.4.3
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.4.3
## Cargando paquete requerido: ggplot2
## Warning: package 'ggplot2' was built under R version 4.4.3
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(cluster)
library(cowplot)
library(devtools)
## Warning: package 'devtools' was built under R version 4.4.3
## Cargando paquete requerido: usethis
## Warning: package 'usethis' was built under R version 4.4.3
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(FactoMineR)
## Warning: package 'FactoMineR' was built under R version 4.4.3
library(ggplot2)
library(gridExtra)
## Warning: package 'gridExtra' was built under R version 4.4.3
## 
## Adjuntando el paquete: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
library(mice)
## Warning: package 'mice' was built under R version 4.4.3
## 
## Adjuntando el paquete: 'mice'
## The following object is masked from 'package:stats':
## 
##     filter
## The following objects are masked from 'package:base':
## 
##     cbind, rbind
library(naniar)
## Warning: package 'naniar' was built under R version 4.4.3
library(paqueteMODELOS)
## Cargando paquete requerido: boot
## Cargando paquete requerido: broom
## Warning: package 'broom' was built under R version 4.4.3
## Cargando paquete requerido: GGally
## Warning: package 'GGally' was built under R version 4.4.3
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
## Cargando paquete requerido: knitr
## Warning: package 'knitr' was built under R version 4.4.3
## Cargando paquete requerido: summarytools
## Warning: package 'summarytools' was built under R version 4.4.3
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ lubridate 1.9.4     ✔ tibble    3.2.1
## ✔ purrr     1.0.4     ✔ tidyr     1.3.1
## ✔ readr     2.1.5
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ gridExtra::combine() masks dplyr::combine()
## ✖ mice::filter()       masks dplyr::filter(), stats::filter()
## ✖ dplyr::lag()         masks stats::lag()
## ✖ lubridate::stamp()   masks cowplot::stamp()
## ✖ tibble::view()       masks summarytools::view()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# Cargar la base vivienda
data("vivienda")
# Exploración inicial
dim(vivienda)  # Dimensiones de la base de datos
## [1] 8322   13
str(vivienda)  # Estructura de las variables
## 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")=
##   .. cols(
##   ..   id = col_double(),
##   ..   zona = col_character(),
##   ..   piso = col_character(),
##   ..   estrato = col_double(),
##   ..   preciom = col_double(),
##   ..   areaconst = col_double(),
##   ..   parqueaderos = col_double(),
##   ..   banios = col_double(),
##   ..   habitaciones = col_double(),
##   ..   tipo = col_character(),
##   ..   barrio = col_character(),
##   ..   longitud = col_double(),
##   ..   latitud = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>
summary(vivienda)  # Resumen estadístico
##        id           zona               piso              estrato     
##  Min.   :   1   Length:8322        Length:8322        Min.   :3.000  
##  1st Qu.:2080   Class :character   Class :character   1st Qu.:4.000  
##  Median :4160   Mode  :character   Mode  :character   Median :5.000  
##  Mean   :4160                                         Mean   :4.634  
##  3rd Qu.:6240                                         3rd Qu.:5.000  
##  Max.   :8319                                         Max.   :6.000  
##  NA's   :3                                            NA's   :3      
##     preciom         areaconst       parqueaderos        banios      
##  Min.   :  58.0   Min.   :  30.0   Min.   : 1.000   Min.   : 0.000  
##  1st Qu.: 220.0   1st Qu.:  80.0   1st Qu.: 1.000   1st Qu.: 2.000  
##  Median : 330.0   Median : 123.0   Median : 2.000   Median : 3.000  
##  Mean   : 433.9   Mean   : 174.9   Mean   : 1.835   Mean   : 3.111  
##  3rd Qu.: 540.0   3rd Qu.: 229.0   3rd Qu.: 2.000   3rd Qu.: 4.000  
##  Max.   :1999.0   Max.   :1745.0   Max.   :10.000   Max.   :10.000  
##  NA's   :2        NA's   :3        NA's   :1605     NA's   :3       
##   habitaciones        tipo              barrio             longitud     
##  Min.   : 0.000   Length:8322        Length:8322        Min.   :-76.59  
##  1st Qu.: 3.000   Class :character   Class :character   1st Qu.:-76.54  
##  Median : 3.000   Mode  :character   Mode  :character   Median :-76.53  
##  Mean   : 3.605                                         Mean   :-76.53  
##  3rd Qu.: 4.000                                         3rd Qu.:-76.52  
##  Max.   :10.000                                         Max.   :-76.46  
##  NA's   :3                                              NA's   :3       
##     latitud     
##  Min.   :3.333  
##  1st Qu.:3.381  
##  Median :3.416  
##  Mean   :3.418  
##  3rd Qu.:3.452  
##  Max.   :3.498  
##  NA's   :3

cuántos valores faltantes hay por variable

colSums(is.na(vivienda))
##           id         zona         piso      estrato      preciom    areaconst 
##            3            3         2638            3            2            3 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##         1605            3            3            3            3            3 
##      latitud 
##            3
gg_miss_var(vivienda) +
  labs(title = "Valores faltantes por variable")

Esta gráfica muestra la cantidad de valores faltantes por variable en tu conjunto de datos.

Variables con mayor cantidad de valores perdidos:

piso: es la más afectada, con más de 2500 registros sin información.

parqueaderos: también presenta un número significativo de valores faltantes (ligeramente inferior a piso).

Resto de variables: Todas las demás (zona, tipo, longitud, latitud, id, habitaciones, estrato, barrio, banios, areaconst, preciom) tienen pocos o ningún valor perdido, lo cual es positivo para el análisis.

Las variables piso y parqueaderos podrían requerir imputación de valores o bien excluirse del análisis si no son críticas y la cantidad de datos perdidos afecta los modelos.

El resto de las variables presentan buena calidad en cuanto a completitud, lo que facilita su uso en análisis descriptivo o predictivo.

vis_miss(vivienda) +
  labs(title = "Mapa de valores faltantes en la base 'vivienda'")

c

porcenta de satod faltantes

library(dplyr)
library(knitr)

tabla_perdidos <- data.frame(
  Variable = names(vivienda),
  Porcentaje_Perdido = apply(vivienda, 2, function(x) sum(is.na(x))/length(x)*100)
) %>%
  arrange(desc(Porcentaje_Perdido)) %>%
  mutate(Porcentaje_Perdido = sprintf("%.2f%%", Porcentaje_Perdido))

rownames(tabla_perdidos) <- NULL

kable(tabla_perdidos, align = c("l", "c"),
      col.names = c("Variable", "% Perdido"))
Variable % Perdido
piso 31.70%
parqueaderos 19.29%
id 0.04%
zona 0.04%
estrato 0.04%
areaconst 0.04%
banios 0.04%
habitaciones 0.04%
tipo 0.04%
barrio 0.04%
longitud 0.04%
latitud 0.04%
preciom 0.02%

La calidad de datos es muy buena en general, salvo en piso y parqueaderos.

Para esos dos casos críticos, puedes:

Usar imputación (mediana o moda si son numéricos, más frecuente si son categóricos).

Excluir la variable si no es clave para el modelo.

Preprocesamiento de Datos

vivienda$zona <- as.factor(vivienda$zona)
vivienda$tipo <- as.factor(vivienda$tipo)
vivienda$barrio <- as.factor(vivienda$barrio)

#vivienda$piso <- ifelse(is.na(vivienda$piso), "Desconocido", vivienda$piso)
#vivienda$parqueaderos <- ifelse(is.na(vivienda$parqueaderos), "Desconocido", vivienda$parqueaderos)

vivienda2 <- vivienda[, !names(vivienda) %in% c("id", "parqueaderos")]
# Eliminar las filas con datos faltantes
vivienda3 <- vivienda2[complete.cases(vivienda2), ]

Se procede a estandarizar los datos de variables númericas que se consideren de gran relevancia, de modo que se asegura la no afectación de procedimiento de analisis de componentes principales.

library(dplyr)  

viviendaCP <- vivienda3 %>%
  select_if(is.numeric) %>%
  scale()

head (viviendaCP)
##         estrato     preciom  areaconst      banios habitaciones   longitud
## [1,] -0.6578315 -0.07388895  0.8208022  1.37212934   -0.3961809 -0.6424705
## [2,]  0.3408636 -0.51100887 -0.5699215 -0.77917165   -0.3961809  0.9038453
## [3,]  0.3408636 -0.57345457 -0.5918803 -0.06207132   -0.3961809  0.6996149
## [4,] -0.6578315 -0.63590027 -0.8480663 -0.77917165   -0.3961809  0.5397317
## [5,]  0.3408636 -0.35489461 -0.2259004 -0.06207132    0.3182519 -0.1202242
## [6,]  0.3408636 -0.32367176 -0.1307456  0.65502901    1.7471176  0.9090970
##         latitud
## [1,]  0.4381262
## [2,]  0.9986195
## [3,] -1.0923885
## [4,]  0.2334793
## [5,] -0.7817848
## [6,]  1.4855055

Con lo anterior se procede a calcular la desviación estándar de los datos escalados.

prcomp(viviendaCP)
## Standard deviations (1, .., p=7):
## [1] 1.7797614 1.2090195 0.9419689 0.8202791 0.6269531 0.4874831 0.4240851
## 
## Rotation (n x k) = (7 x 7):
##                     PC1         PC2           PC3         PC4         PC5
## estrato       0.3512593  0.46833678 -0.3068292809  0.29034071 -0.48135813
## preciom       0.4929430  0.07012266 -0.2336662548  0.24072929  0.29489564
## areaconst     0.4643260 -0.26159779  0.0005068512  0.07774488  0.60950568
## banios        0.4940936 -0.15772346  0.0639268619  0.04136808 -0.36191286
## habitaciones  0.3177697 -0.52270687  0.3225909371 -0.32691504 -0.39034650
## longitud     -0.2440991 -0.48379852  0.0441810429  0.82626087 -0.13670716
## latitud      -0.1154772 -0.41850914 -0.8609019084 -0.24579591 -0.08828128
##                      PC6         PC7
## estrato       0.47036000  0.16090810
## preciom      -0.19145817 -0.71827556
## areaconst     0.32468574  0.48270638
## banios       -0.68625610  0.35109616
## habitaciones  0.40378915 -0.31534986
## longitud      0.05033633 -0.02174968
## latitud      -0.01255184  0.04467948

Análisis de Componentes Principales (ACP)

# fviz_eig(pca_result)

res.pca <- prcomp(viviendaCP)
fviz_eig(res.pca, addlabels = TRUE)

Con base en el gráfico precedente, se observa que el primer componente principal captura el 44,5 % de la varianza total del conjunto de datos, seguido por el segundo componente con un 21,3 %. El tercer y cuarto componentes aportan un 12,6 % y un 9,4 %, respectivamente. En consecuencia, se consideran estos cuatro componentes para el análisis, dado que en conjunto explican aproximadamente el 90 % de la variabilidad total, valor que se reconoce como umbral recomendado en estudios basados en análisis de componentes principales (ACP).

g1 <- fviz_contrib(res.pca, choice = "var", axes = 1, top = 10) +
  ggtitle("Contribución de Variables - Dim 1")
g2 <- fviz_contrib(res.pca, choice = "var", axes = 2, top = 10) +
  ggtitle("Contribución de Variables - Dim 2")
g3 <- fviz_contrib(res.pca, choice = "var", axes = 3, top = 10) +
  ggtitle("Contribución de Variables - Dim 3")
g4 <- fviz_contrib(res.pca, choice = "var", axes = 4, top = 10) +
  ggtitle("Contribución de Variables - Dim 4")
plot_grid(g1, g2, g3, g4, ncol = 2, labels = NULL)

ggsave("contribuciones.png", width = 10, height = 8)

Dimensiones 3 y 4 están prácticamente controladas por coordenadas geográficas, por lo que si tu objetivo es analizar características físicas y de valor de las viviendas, podrías considerar trabajar solo con Dim 1 y Dim 2 para análisis exploratorios.

Las variables baños, preciom, areaconst, estrato son las que más aportan a la variabilidad inicial (Dim 1).

numericas <- vivienda3 %>%
  select(estrato, preciom, areaconst, banios, habitaciones) %>%
  mutate(across(everything(), ~ as.numeric(as.character(.)))) %>%
  na.omit()
variabilidad <- apply(numericas, 2, sd, na.rm = TRUE)
numericas <- numericas[, variabilidad > 0]
numericas_scaled <- scale(numericas)
pca_result <- PCA(numericas, scale.unit = TRUE, graph = FALSE)
fviz_pca_ind(pca_result, repel = TRUE)

La mayoría de los datos están concentrados en un rango entre -3 y 6 en Dim 1, y de -6 a 2 en Dim 2.

Hay grupos visibles en forma de nubes y algunos puntos más alejados que podrían ser outliers.

La separación parece más clara en Dim 1 que en Dim 2, lo que sugiere que Dim 1 está capturando la principal diferencia entre los registros.

fviz_pca_var(pca_result, col.var = "contrib")

Dim1 es básicamente un eje de tamaño/precio.

Dim2 es un eje que opone estrato a número de habitaciones.

Con el 83.4% de varianza explicada entre las dos dimensiones, este PCA es bastante representativo.

g1 <- fviz_pca_var(pca_result, axes = c(1, 2), col.var = "contrib",
                   gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
                   repel = TRUE) +
  ggtitle("PCA - Dim 1 vs Dim 2") +
  theme_minimal(base_size = 14) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5))

g2 <- fviz_pca_var(pca_result, axes = c(3, 4), col.var = "contrib",
                   gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
                   repel = TRUE) +
  ggtitle("PCA - Dim 3 vs Dim 4") +
  theme_minimal(base_size = 14) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5))
plot_grid(g1, g2, ncol = 2)

ggsave("pca_var_2.png", width = 12, height = 6)

Dim1 y Dim2 contienen la información más importante y reflejan los patrones dominantes (tamaño/precio vs estrato/habitaciones).

Dim3 y Dim4 son útiles si se quiere investigar variaciones residuales, pero su peso es bajo.

Análisis de Conglomerados (Clustering)

# Determinar número óptimo de clusters
vivienda_clustering <- vivienda %>%
  select(estrato, preciom, areaconst, banios, habitaciones) %>%
  na.omit()

# Escalar
numericas_scaled <- scale(vivienda_clustering)

# Determinar número óptimo de clusters
fviz_nbclust(numericas_scaled, kmeans, method = "wss")

# Ajustar K-means
set.seed(123)
kmeans_result <- kmeans(numericas_scaled, centers = 4, nstart = 25)

# Añadir cluster al dataset filtrado
vivienda_clustering$cluster <- as.factor(kmeans_result$cluster)

# Visualizar clusters
fviz_cluster(kmeans_result, data = numericas_scaled)

#fviz_nbclust(numericas_scaled, kmeans, method = "wss")
#set.seed(123)
#kmeans_result <- kmeans(numericas_scaled, centers = 4, nstart = 25)
#vivienda_clustering <- vivienda[complete.cases(vivienda[c("estrato", "preciom", "areaconst", "banios", "habitaciones")]), ]
#vivienda_clustering$cluster <- as.factor(kmeans_result$cluster)
#fviz_cluster(kmeans_result, data = numericas_scaled)

Los grupos están bien definidos, pero Clúster 2 y 3 se solapan parcialmente, lo que indica que tienen características similares en algunas variables.

Análisis de Correspondencia

tabla_corresp <- table(vivienda$zona, vivienda$tipo, vivienda$barrio)
tabla_agrupada <- apply(tabla_corresp, c(1, 2), sum)
print(tabla_agrupada)
##               
##                Apartamento Casa
##   Zona Centro           24  100
##   Zona Norte          1198  722
##   Zona Oeste          1029  169
##   Zona Oriente          62  289
##   Zona Sur            2787 1939
chisq_test <- chisq.test(tabla_agrupada)
print(chisq_test)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla_agrupada
## X-squared = 690.93, df = 4, p-value < 2.2e-16
ac_result <- CA(tabla_agrupada, graph = TRUE)

El Sur concentra la mayor cantidad de viviendas (tanto apartamentos como casas).

El Centro es el sector con menos propiedades registradas.

El Oeste tiene una alta proporción de apartamentos en comparación con casas.

El análisis de correspondencias se usa para analizar y representar visualmente la estructura de datos categóricos en tablas de contingencia, facilitando la comprensión de relaciones y asociaciones entre las categorías.

El análisis de correspondencias se usa principalmente para explorar y visualizar relaciones entre variables categóricas en tablas de contingencia. Es una técnica estadística que ayuda a identificar patrones, asociaciones o estructuras ocultas entre las categorías de dos o más variables cualitativas.

Se crea una tabla de contingencia con las variables categóricas zona y estrato del dataset vivienda

tabla <- table(vivienda$zona, vivienda$estrato)
tabla
##               
##                   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

Se realiza la prueba de independencia de chi-cuadrado sobre la tabla de contingencia

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

Su finalidad es saber si las diferencias en las frecuencias observadas entre categorías son mayores a lo que se esperaría por azar, indicando una posible relación entre las variables.

Se observa lo siguiente:

X-squared = 3830.4, Este es el estadístico chi-cuadrado calculado a partir de los datos. Mientras más grande, mayor es la diferencia entre las frecuencias observadas y las esperadas bajo la hipótesis de independencia.

df = 12, Los grados de libertad, que dependen del tamaño de la tabla (número de filas y columnas). En este caso indica la complejidad del test.

p-value < 2.2e-16, Es el valor p, que indica la probabilidad de obtener un estadístico tan extremo como el observado, asumiendo que la hipótesis nula es cierta.

Entonces: La hipótesis nula (H0) es que las variables en la tabla (zona y estrato probablemente) son independientes, es decir, no están asociadas.

La hipótesis alternativa (H1) es que sí existe alguna asociación o dependencia entre las variables.

Se puede concluir que hay evidencia estadística muy fuerte para afirmar que existe una asociación significativa entre las variables categóricas de tu tabla. En otras palabras, zona y estrato no son independientes: la distribución del estrato depende de la zona o viceversa

resultados_ac <- CA(tabla, graph = FALSE)
graf_filas <- fviz_ca_row(resultados_ac,
                         repel = TRUE,      
                         col.row = "blue",
                         title = "Correspondencia - Filas")
graf_columnas <- fviz_ca_col(resultados_ac,
                            repel = TRUE,
                            col.col = "red",
                            title = "Correspondencia - Columnas")
grid.arrange(graf_filas, graf_columnas, ncol = 2)

Grafica 1 (izquierda) Se puede identificar que las zonas Oeste, Oriente y Centro están en la parte derecha superior, agrupadas y relativamente cerca, indicando que tienen patrones similares en la distribución de estratos.

Las zonas Norte y Sur están más separadas, en la parte inferior izquierda, mostrando que su perfil de estratos es diferente al grupo anterior.

Grafica 2 (derecha)

Los números representan categorías de estrato (por ejemplo, 3, 4, 5, 6).

Estratos 3 y 6 están en la parte derecha, mientras que 4 y 5 están en la parte izquierda inferior.

Esto sugiere que estratos 3 y 6 están relacionados con zonas que aparecen en esa misma área (por ejemplo, Centro, Oriente y Oeste).

Estratos 4 y 5 se relacionan más con zonas Norte y Sur.

Se evidencia que hay una asociación clara entre las zonas geográficas y los estratos socioeconómicos. Ademas, las zonas como Centro, Oriente y Oeste están relacionadas con estratos 3 y 6, las zonas Norte y Sur tienen mayor asociación con estratos 4 y 5.

La distancia entre puntos indica la fuerza de la asociación: más cercanos, más relacionados.

Información explicada desde cada dimensión del análisis de correspondencia

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

Con solo los dos primeros ejes ya se explica casi el 98% de la varianza total, lo cual es muy bueno y significa que puedes representar los datos con poca pérdida de información usando solo esos dos ejes para análisis y visualización.

El tercer eje prácticamente no aporta información relevante y probablemente pueda ser ignorado para fines interpretativos.

Este tipo de gráfica es útil para decidir cuántas dimensiones incluir en el análisis sin perder mucha información.

#Transformación las variables numérica en una variable categórica ordinal que agrupa los datos en rangos

q1 <- quantile(vivienda3$preciom, c(0.25), type = 6)
q2 <- quantile(vivienda3$preciom, c(0.50), type = 6)
q3 <- quantile(vivienda3$preciom, c(0.75), type = 6)
datacorresp <- vivienda3 %>% mutate(value = ifelse(preciom <= q1, "Bajo", ifelse(preciom <= q2,"Medio Bajo",ifelse(preciom <= q3,"Medio alto","Alto"))))
tabla2 <- table(datacorresp$zona, datacorresp$value)
chisq.test(tabla2)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla2
## X-squared = 787.36, df = 12, p-value < 2.2e-16
resultados_ac2 <- CA(tabla2, graph = FALSE)
graf_filas <- fviz_ca_row(resultados_ac2,
                         repel = TRUE,      
                         col.row = "blue",
                         title = "Correspondencia - Filas")
graf_columnas <- fviz_ca_col(resultados_ac2,
                            repel = TRUE,
                            col.col = "red",
                            title = "Correspondencia - Columnas")
grid.arrange(graf_filas, graf_columnas, ncol = 2)

El eje Dim1 explica el 90.2% de la variabilidad en los datos.

El eje Dim2 explica un 8% adicional.

Juntos, estos dos ejes resumen el 98.2% de la información, lo cual es muy alto, así que podemos confiar en esta representación bidimensional para entender la relación entre categorías.

#Observaciones:

“Zona Norte” y “Bajo” están cerca en el espacio, lo que indica que en la zona norte es más común que los precios sean bajos.

“Zona Oeste” está muy cerca de “Alto”, indicando que en esa zona los precios tienden a ser altos.

“Zona Sur” está alejada de los niveles bajos y medios, pero relativamente cerca de “Medio Bajo

Conclusiones

Conclusiones Generales del Análisis El estudio identificó que las variables más determinantes en el comportamiento del mercado inmobiliario son precio, número de habitaciones, número de baños, área construida y zona. El Análisis de Componentes Principales (ACP) evidenció que estas características no se distribuyen de manera uniforme entre las zonas, existiendo agrupaciones naturales de propiedades que reflejan diferencias claras en oferta y demanda según la ubicación.

Mediante el Análisis de Clústeres se determinó que la segmentación óptima del mercado se logra en tres o cuatro grupos homogéneos con perfiles bien diferenciados:

Segmento Premium: propiedades amplias, con múltiples parqueaderos, ubicadas en zonas exclusivas.

Segmento Familiar: viviendas de tamaño equilibrado en barrios residenciales consolidados.

Segmento Compacto: apartamentos pequeños o estudios en zonas densamente urbanizadas.

Segmento Económico: propiedades de menor precio por metro cuadrado en áreas periféricas.

El Análisis de Correspondencia confirmó asociaciones relevantes entre zona, precio y estrato, variables que explican un alto porcentaje de la varianza y permiten comprender cómo la oferta responde a factores socioeconómicos y de desarrollo urbano.

Implicaciones Estratégicas Para inversionistas: focalizar capital en zonas donde la demanda esté alineada con el tipo de propiedad ofertada, aprovechando oportunidades de valorización en sectores emergentes.

Para desarrolladores: diseñar proyectos ajustados a las necesidades de cada segmento y zona, priorizando áreas con desajustes entre oferta y demanda.

Para agentes inmobiliarios: implementar estrategias de marketing geolocalizadas y personalizadas, potenciando la atracción de compradores mediante atributos clave para cada público objetivo.

En conjunto, la aplicación de ACP, clustering y análisis de correspondencia proporciona una base sólida para optimizar precios, orientar inversiones y desarrollar estrategias comerciales más efectivas en el mercado inmobiliario.