Introducción

Una empresa inmobiliaria líder en una gran ciudad está buscando comprender en profundidad el mercado de viviendas urbanas para tomar decisiones estratégicas más informadas. La empresa posee una base de datos extensa que contiene información detallada sobre diversas propiedades residenciales disponibles en el mercado. Se requiere realizar un análisis holístico de estos datos para identificar patrones, relaciones y segmentaciones relevantes que permitan mejorar la toma de decisiones en cuanto a la compra, venta y valoración de propiedades.

1. Datos iniciales

Se inicia con la instalación y carga de paquetes, que contienen la base de datos “vivienda_faltantes”. Se cuenta con un total de 8,322 registros y 13 variables.

  • id: Identificador único de la vivienda
  • zona: Zona de la ciudad (sur, norte, oriente, occidente)
  • piso: Piso en el que está ubicada la vivienda
  • estrato: Estrato socioeconómico
  • preciom: Precio en millones de pesos
  • areaconst: Área construida en metros cuadrados
  • parqueaderos: Número de parqueaderos
  • banios: Número de baños
  • habitaciones: Número de habitaciones
  • tipo: Tipo de vivienda (casa o apartamento)
  • barrio: Barrio
  • longitud: Coordenada de longitud
  • latitud: Coordenada de latitud

1.1. Análisis exploratorio de los datos

# Cargar los datos
data("vivienda")

# Visión general de los datos
glimpse(vivienda)
## Rows: 8,322
## Columns: 13
## $ id           <dbl> 1147, 1169, 1350, 5992, 1212, 1724, 2326, 4386, 1209, 159…
## $ zona         <chr> "Zona Oriente", "Zona Oriente", "Zona Oriente", "Zona Sur…
## $ piso         <chr> NA, NA, NA, "02", "01", "01", "01", "01", "02", "02", "02…
## $ estrato      <dbl> 3, 3, 3, 4, 5, 5, 4, 5, 5, 5, 6, 4, 5, 6, 4, 5, 5, 4, 5, …
## $ preciom      <dbl> 250, 320, 350, 400, 260, 240, 220, 310, 320, 780, 750, 62…
## $ areaconst    <dbl> 70, 120, 220, 280, 90, 87, 52, 137, 150, 380, 445, 355, 2…
## $ parqueaderos <dbl> 1, 1, 2, 3, 1, 1, 2, 2, 2, 2, NA, 3, 2, 2, 1, 4, 2, 2, 2,…
## $ banios       <dbl> 3, 2, 2, 5, 2, 3, 2, 3, 4, 3, 7, 5, 6, 2, 4, 4, 4, 3, 2, …
## $ habitaciones <dbl> 6, 3, 4, 3, 3, 3, 3, 4, 6, 3, 6, 5, 6, 2, 5, 5, 4, 3, 3, …
## $ tipo         <chr> "Casa", "Casa", "Casa", "Casa", "Apartamento", "Apartamen…
## $ barrio       <chr> "20 de julio", "20 de julio", "20 de julio", "3 de julio"…
## $ longitud     <dbl> -76.51168, -76.51237, -76.51537, -76.54000, -76.51350, -7…
## $ latitud      <dbl> 3.43382, 3.43369, 3.43566, 3.43500, 3.45891, 3.36971, 3.4…

Se inicia identificando por cada variable el total de datos faltantes

md.pattern(vivienda,rotate.names = TRUE)

##      preciom id zona estrato areaconst banios habitaciones tipo barrio longitud
## 4808       1  1    1       1         1      1            1    1      1        1
## 1909       1  1    1       1         1      1            1    1      1        1
## 876        1  1    1       1         1      1            1    1      1        1
## 726        1  1    1       1         1      1            1    1      1        1
## 1          1  0    0       0         0      0            0    0      0        0
## 2          0  0    0       0         0      0            0    0      0        0
##            2  3    3       3         3      3            3    3      3        3
##      latitud parqueaderos piso     
## 4808       1            1    1    0
## 1909       1            1    0    1
## 876        1            0    1    1
## 726        1            0    0    2
## 1          0            0    0   12
## 2          0            0    0   13
##            3         1605 2638 4275

Siendo la variable “id” un identificador unico, se procede a eliminar duplicados y NA de la variable “id”, obteniendo que las variables “piso” y “parqueaderos” son las unicas con datos faltantes a tratar

# Contar el total de registros duplicados basados en la variable "id"
total_duplicados_id <- sum(duplicated(vivienda$id))

# Eliminar registros duplicados basados en la variable "id"
id_sin_dup <- distinct(vivienda, id, .keep_all = TRUE)

#Eliminar registros faltantes (NA) variable "id"
id_sin_dup_na <- id_sin_dup %>% filter(!is.na(id))

faltantes <- colSums(is.na(id_sin_dup_na)) %>% as.data.frame()
faltantes
bd_sin_dup <- id_sin_dup_na #Base sin "id" duplicados

Se revisan las variables nominales “zona” - “tipo”

# Revisión variables nominales
table(bd_sin_dup$zona)
## 
##  Zona Centro   Zona Norte   Zona Oeste Zona Oriente     Zona Sur 
##          124         1920         1198          351         4726
table(bd_sin_dup$tipo)
## 
## Apartamento        Casa 
##        5100        3219

Finalmente, se hace un analisis sobre las variables con datos faltantes:

plot_missing(bd_sin_dup)

# Tabla pisos_tipo
bd_sin_dup$piso <- as.numeric(bd_sin_dup$piso)
pisos_tipo <- table1(~ piso| tipo, data=bd_sin_dup)
kable(pisos_tipo, caption = "Distribución de pisos por tipo")
Distribución de pisos por tipo
Apartamento Casa Overall
(N=5100) (N=3219) (N=8319)
piso
Mean (SD) 4.63 (2.81) 2.14 (0.860) 3.77 (2.61)
Median [Min, Max] 4.00 [1.00, 12.0] 2.00 [1.00, 10.0] 3.00 [1.00, 12.0]
Missing 1381 (27.1%) 1254 (39.0%) 2635 (31.7%)
# Tabla parqueadero_tipo
parqueadero_tipo <- table1(~ parqueaderos | tipo, data=bd_sin_dup)
kable(parqueadero_tipo, caption = "Distribución de parqueaderos por tipo")
Distribución de parqueaderos por tipo
Apartamento Casa Overall
(N=5100) (N=3219) (N=8319)
parqueaderos
Mean (SD) 1.57 (0.743) 2.29 (1.47) 1.84 (1.12)
Median [Min, Max] 1.00 [1.00, 10.0] 2.00 [1.00, 10.0] 2.00 [1.00, 10.0]
Missing 869 (17.0%) 733 (22.8%) 1602 (19.3%)

Se realiza una imputación basada en la mediana, donde se empleó la mediana calculada para cada tipo de vivienda para completar los valores faltantes en las variables correspondientes a ese tipo de vivienda.

# Calcular medianas por tipo de vivienda
medianas <- bd_sin_dup %>%
  group_by(tipo) %>%
  summarise(mediana_piso = median(piso, na.rm = TRUE),
            mediana_parqueaderos = median(parqueaderos, na.rm = TRUE))
medianas
# Completar valores faltantes usando la mediana correspondiente
bd_clean <- bd_sin_dup %>%
  left_join(medianas, by = "tipo") %>%  # Unir las medianas calculadas al dataframe original
  mutate(piso = if_else(is.na(piso), mediana_piso, piso),
         parqueaderos = if_else(is.na(parqueaderos), mediana_parqueaderos,
                                parqueaderos)) %>%
  select(-mediana_piso, -mediana_parqueaderos)  # Eliminar columnas auxiliares

colSums(is.na(bd_clean))
##           id         zona         piso      estrato      preciom    areaconst 
##            0            0            0            0            0            0 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##            0            0            0            0            0            0 
##      latitud 
##            0
glimpse(bd_clean)
## Rows: 8,319
## Columns: 13
## $ id           <dbl> 1147, 1169, 1350, 5992, 1212, 1724, 2326, 4386, 1209, 159…
## $ zona         <chr> "Zona Oriente", "Zona Oriente", "Zona Oriente", "Zona Sur…
## $ piso         <dbl> 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, …
## $ estrato      <dbl> 3, 3, 3, 4, 5, 5, 4, 5, 5, 5, 6, 4, 5, 6, 4, 5, 5, 4, 5, …
## $ preciom      <dbl> 250, 320, 350, 400, 260, 240, 220, 310, 320, 780, 750, 62…
## $ areaconst    <dbl> 70, 120, 220, 280, 90, 87, 52, 137, 150, 380, 445, 355, 2…
## $ parqueaderos <dbl> 1, 1, 2, 3, 1, 1, 2, 2, 2, 2, 2, 3, 2, 2, 1, 4, 2, 2, 2, …
## $ banios       <dbl> 3, 2, 2, 5, 2, 3, 2, 3, 4, 3, 7, 5, 6, 2, 4, 4, 4, 3, 2, …
## $ habitaciones <dbl> 6, 3, 4, 3, 3, 3, 3, 4, 6, 3, 6, 5, 6, 2, 5, 5, 4, 3, 3, …
## $ tipo         <chr> "Casa", "Casa", "Casa", "Casa", "Apartamento", "Apartamen…
## $ barrio       <chr> "20 de julio", "20 de julio", "20 de julio", "3 de julio"…
## $ longitud     <dbl> -76.51168, -76.51237, -76.51537, -76.54000, -76.51350, -7…
## $ latitud      <dbl> 3.43382, 3.43369, 3.43566, 3.43500, 3.45891, 3.36971, 3.4…

2. Análisis descriptivo

Durante esta etapa se lleva a cabo un analisis más detallado de las variables, mediante métodos que permiten resumir y presentar los datos de manera informativa, empleando medidas de tendencia central, dispersión, frecuencias y de distribución para comprender la naturaleza de los datos en profundidad y la identificación de posibles patrones o tendencias.

2.1. Análisis descriptivo univariable

Medidas tendencia central

variables <-  bd_clean[, c("preciom", "areaconst", "banios", "habitaciones", 
                           "piso","parqueaderos")]
summarytools::descr(variables)
## Descriptive Statistics  
## variables  
## N: 8319  
## 
##                     areaconst    banios   habitaciones   parqueaderos      piso   preciom
## ----------------- ----------- --------- -------------- -------------- --------- ---------
##              Mean      174.93      3.11           3.61           1.76      3.54    433.90
##           Std.Dev      142.96      1.43           1.46           1.04      2.26    328.67
##               Min       30.00      0.00           0.00           1.00      1.00     58.00
##                Q1       80.00      2.00           3.00           1.00      2.00    220.00
##            Median      123.00      3.00           3.00           2.00      3.00    330.00
##                Q3      229.00      4.00           4.00           2.00      4.00    540.00
##               Max     1745.00     10.00          10.00          10.00     12.00   1999.00
##               MAD       84.51      1.48           1.48           1.48      1.48    207.56
##               IQR      149.00      2.00           1.00           1.00      2.00    320.00
##                CV        0.82      0.46           0.40           0.59      0.64      0.76
##          Skewness        2.69      0.93           1.63           2.50      1.59      1.85
##       SE.Skewness        0.03      0.03           0.03           0.03      0.03      0.03
##          Kurtosis       12.91      1.13           3.98           9.98      2.62      3.67
##           N.Valid     8319.00   8319.00        8319.00        8319.00   8319.00   8319.00
##         Pct.Valid      100.00    100.00         100.00         100.00    100.00    100.00
plot_histogram(variables)

De acuerdo con el análisis, se logra evidenciar que:

  • Area construida: Viviendas con un area construida entre 100m² y 200m².
  • Estrato: Viendas ubicadas en estratos 4 y 5 de la ciudad de Cali.
  • Pisos: La mayoría de las viviendas estan ubicadas entre los pisos 2 y 3.
  • Habitaciones: Viviendas en su mayoria con minimo 3 habitaciones.
  • Parqueadero: Viviendas cuentan con al menos un parqueadero.
  • Baños: Cuentan con 2 a 3 baños.
  • Precio: El precio medio es de 330 millones, con un valor maximo de 2000 millones.

Zona de residencia

summarytools::freq(bd_clean$zona)
## Frequencies  
## bd_clean$zona  
## Type: Character  
## 
##                      Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ------------------ ------ --------- -------------- --------- --------------
##        Zona Centro    124      1.49           1.49      1.49           1.49
##         Zona Norte   1920     23.08          24.57     23.08          24.57
##         Zona Oeste   1198     14.40          38.97     14.40          38.97
##       Zona Oriente    351      4.22          43.19      4.22          43.19
##           Zona Sur   4726     56.81         100.00     56.81         100.00
##               <NA>      0                               0.00         100.00
##              Total   8319    100.00         100.00    100.00         100.00
frecuencia_zona <- table(bd_clean$zona)
porcentajes <- prop.table(frecuencia_zona) * 100
pie(porcentajes, main = "Distribución por Zonas", 
    labels = paste(names(porcentajes),": ",format(porcentajes, digits = 2), "%"))

Aproximadamente el 57% de las viviendas vendidas se encuentran ubicadas al sur de la ciudad de Cali.

Tipo de vivienda

summarytools::freq(bd_clean$tipo)
## Frequencies  
## bd_clean$tipo  
## Type: Character  
## 
##                     Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ----------------- ------ --------- -------------- --------- --------------
##       Apartamento   5100     61.31          61.31     61.31          61.31
##              Casa   3219     38.69         100.00     38.69         100.00
##              <NA>      0                               0.00         100.00
##             Total   8319    100.00         100.00    100.00         100.00
frecuencia_tipo <- table(bd_clean$tipo)
porcentajes2 <- prop.table(frecuencia_tipo) * 100
pie(porcentajes2, main = "Distribución por tipo de vivienda", 
    labels = paste(names(porcentajes2),": ",format(porcentajes2, digits = 2), "%"),
    col = c("#0d3b66", "#f4d35e"))

El 61% de las viviendas vendidas son apartamentos.

Estrato socioéconomico

summarytools::freq(bd_clean$estrato)
## Frequencies  
## bd_clean$estrato  
## Type: Numeric  
## 
##               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ----------- ------ --------- -------------- --------- --------------
##           3   1453     17.47          17.47     17.47          17.47
##           4   2129     25.59          43.06     25.59          43.06
##           5   2750     33.06          76.11     33.06          76.11
##           6   1987     23.89         100.00     23.89         100.00
##        <NA>      0                               0.00         100.00
##       Total   8319    100.00         100.00    100.00         100.00
frecuencia_estrato <- table(bd_clean$estrato)
porcentajes_estrato <- prop.table(frecuencia_estrato) * 100
barplot(frecuencia_estrato, 
        main = "Distribución por Estrato",xlab = "Estrato",ylab = "Frecuencia",
        col = "#0d3b66",border = "white")
text(x = seq_along(frecuencia_estrato), y = frecuencia_estrato,
     labels = paste0(frecuencia_estrato," (", round(porcentajes_estrato, 2), "%)"),
     pos = 3, cex = 0.8)

El 59% de las viviendas se enccuentran en los estrato 4 y 5.

3. Análisis de Componentes Principales (PCA)

El método de Análisis de Componentes Principales (PCA) es aplicable a variables númericas, por lo que inicialmente se debe crear un nuevo conjunto de datos que almacenara estas variables. Estas variables son: “preciom”, “areaconst”, “banios”, “habitaciones”, “piso” y “parqueaderos”.

data_num <- variables # Base con variables numéricas
summarytools::descr(data_num)
## Descriptive Statistics  
## data_num  
## N: 8319  
## 
##                     areaconst    banios   habitaciones   parqueaderos      piso   preciom
## ----------------- ----------- --------- -------------- -------------- --------- ---------
##              Mean      174.93      3.11           3.61           1.76      3.54    433.90
##           Std.Dev      142.96      1.43           1.46           1.04      2.26    328.67
##               Min       30.00      0.00           0.00           1.00      1.00     58.00
##                Q1       80.00      2.00           3.00           1.00      2.00    220.00
##            Median      123.00      3.00           3.00           2.00      3.00    330.00
##                Q3      229.00      4.00           4.00           2.00      4.00    540.00
##               Max     1745.00     10.00          10.00          10.00     12.00   1999.00
##               MAD       84.51      1.48           1.48           1.48      1.48    207.56
##               IQR      149.00      2.00           1.00           1.00      2.00    320.00
##                CV        0.82      0.46           0.40           0.59      0.64      0.76
##          Skewness        2.69      0.93           1.63           2.50      1.59      1.85
##       SE.Skewness        0.03      0.03           0.03           0.03      0.03      0.03
##          Kurtosis       12.91      1.13           3.98           9.98      2.62      3.67
##           N.Valid     8319.00   8319.00        8319.00        8319.00   8319.00   8319.00
##         Pct.Valid      100.00    100.00         100.00         100.00    100.00    100.00

Ya que se presentan diferencias en las escalas de las variables, se realizó la estandarización para su análisis y prevenir que las variables con escalas de valores más grandes sesguen las estimaciones, asegurando que las variables contribuyan manera equitativa en el análisis:

data_numz= scale(data_num) #Se estandarizan los datos
summary(data_numz)
##     preciom          areaconst           banios          habitaciones    
##  Min.   :-1.1437   Min.   :-1.0138   Min.   :-2.17847   Min.   :-2.4702  
##  1st Qu.:-0.6508   1st Qu.:-0.6640   1st Qu.:-0.77812   1st Qu.:-0.4148  
##  Median :-0.3161   Median :-0.3633   Median :-0.07794   Median :-0.4148  
##  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.00000   Mean   : 0.0000  
##  3rd Qu.: 0.3228   3rd Qu.: 0.3782   3rd Qu.: 0.62224   3rd Qu.: 0.2704  
##  Max.   : 4.7620   Max.   :10.9822   Max.   : 4.82330   Max.   : 4.3813  
##       piso          parqueaderos    
##  Min.   :-1.1256   Min.   :-0.7298  
##  1st Qu.:-0.6828   1st Qu.:-0.7298  
##  Median :-0.2400   Median : 0.2273  
##  Mean   : 0.0000   Mean   : 0.0000  
##  3rd Qu.: 0.2028   3rd Qu.: 0.2273  
##  Max.   : 3.7451   Max.   : 7.8840

Teniendo las variables estandarizadas se realiza el cálculo de los componentes principales:

data_pca = prcomp(data_numz) #Calculo de componentes principales
data_pca
## Standard deviations (1, .., p=6):
## [1] 1.8083042 1.0359130 0.8645895 0.6255943 0.5719934 0.4368757
## 
## Rotation (n x k) = (6 x 6):
##                     PC1         PC2        PC3         PC4        PC5
## preciom       0.4563098  0.35271739  0.2352750  0.33933742  0.1786403
## areaconst     0.4801047 -0.02235070  0.0297751  0.46175001 -0.6393381
## banios        0.4772284  0.03718653 -0.2712414  0.08620164  0.6863697
## habitaciones  0.3582706 -0.41625591 -0.6572569 -0.28195653 -0.1844438
## piso         -0.1538954  0.80029142 -0.5464489 -0.05391418 -0.1787679
## parqueaderos  0.4260191  0.24489324  0.3736230 -0.76275821 -0.1491765
##                      PC6
## preciom       0.68187629
## areaconst    -0.38229201
## banios       -0.46772228
## habitaciones  0.39098280
## piso         -0.04877242
## parqueaderos -0.12201278

Visualización de la varianza explicada por cada componente:

fviz_eig(data_pca, addlabels = TRUE) #Variabilidad capturada por cada componente

summary(data_pca)
## Importance of components:
##                          PC1    PC2    PC3     PC4     PC5     PC6
## Standard deviation     1.808 1.0359 0.8646 0.62559 0.57199 0.43688
## Proportion of Variance 0.545 0.1789 0.1246 0.06523 0.05453 0.03181
## Cumulative Proportion  0.545 0.7238 0.8484 0.91366 0.96819 1.00000

Vemos que el primer componente principal explica el 54.5% de la variabilidad contenida en la base de datos y entre los dos primeros hacen el 72.4%, lo cual sugiere que con solo dos componentes principales, se puede resumir gran parte de la variabilidad que contiene la base de datos.

Circulo de correlaciones:

fviz_pca_var(data_pca,col.var = "contrib", 
             gradient.cols = c("#FF7F00",  "#034D94"),repel = TRUE) #Circulo de correlaciones

El círculo de correlaciones nos muestra cómo las variables originales se proyectan en el espacio de los componentes. Se observa que las variables “precio”-“baños”-“area construida” tienen una mayor relación con el segundo componente principal, mientras que la variable “piso” presenta mayor efecto sobre el primer componente.

Las variables “parqueaderos” y “habitaciones” son las que menos contribuyen a la conformación del primer componente principal.

También se observa que el precio de la viviendas y la cantidad de parqueaderos estan correlacionadas, por lo que se puede decir que las viviendas con mayor cantidad de parqueaderos pueden tener precios más altos. Ocurre lo mismo con el área contruida y número de baños, al presentar una correlación alta se puede pensar que las viviendas a mayor área construida tienen más baños.

Contribución de las variables a los componentes principales:

fviz_contrib(data_pca, choice = "var", axes = 1:2) #Contribución de las variables

Se genera un gráfico que muestra la contribución de cada variable a los primeros dos componentes principales, ayudando a identificar qué variables tienen mayor influencia en la formación de los componentes. Se observa que las primeras 4 variables “preciom”, “piso” ,“areaconst”, “baños” tienen las contribuciones más altas, confirmando lo anteriormente dicho.

4. Análisis de conglomerados

Con las variables numericas ya estandarizadas “preciom”, “areaconst”, “banios”, “habitaciones”, “piso” y “parqueaderos”, se utiliza el método del codo para determinar el número óptimo de clusters para el algoritmo K-means. En este caso se sugiere un k=3:

fviz_nbclust(data_numz, kmeans, method = "wss")

Aplicando el algoritmo K-means con 3 centros (clusters) y 25 iniciaciones aleatorias (nstart = 25) para encontrar el mejor agrupamiento. Se muestra la distribución de las observaciones en cada cluster:

set.seed(123)
# Aplicar K-means con el número óptimo de clusters
kmeans_mod <- kmeans(data_numz, centers = 3, nstart = 25)
data_num$cluster = as.factor(kmeans_mod$cluster)
table(data_num$cluster)
## 
##    1    2    3 
##  929 4896 2494
fviz_cluster(kmeans_mod, data = data_numz,
             geom = "point",
             ellipse.type = "convex",
             ggtheme = theme_minimal(),
             main = "Clusters Plot")

colores <- c("#F4A261", "#2A9D8F", "#E9C46A")
ggplot(data_num, aes(x = factor(cluster))) +
  geom_bar(fill = colores) +  
  labs(title = "Distribución de viviendas por clúster",
       x = "Clúster",
       y = "Cantidad de viviendas") +
  theme_minimal() +
  geom_text(stat='count', aes(label=..count..), vjust=-0.5)

# Tabla resumen
resumen_clusters <- data_num %>%
  group_by(cluster) %>%
  summarise(across(everything(), mean, na.rm = TRUE))
print(resumen_clusters)
## # A tibble: 3 × 7
##   cluster preciom areaconst banios habitaciones  piso parqueaderos
##   <fct>     <dbl>     <dbl>  <dbl>        <dbl> <dbl>        <dbl>
## 1 1         1128.     422.    5.17         4.50  3.12         3.78
## 2 2          264.      96.0   2.24         2.87  4.12         1.30
## 3 3          509.     238.    4.06         4.72  2.57         1.92

Se observa que el cluster “2” presenta la mayor concentración con un total de 4.896 viviendas, seguido del clúster 3 que cuenta con 2494 viviendas. Lo cual ayuda a entender cómo se agrupan las viviendas en función de sus características.

  • Clúster 1: Viviendas grandes, caras, con muchas características (baños, habitaciones, parqueaderos).
  • Clúster 2: Viviendas pequeñas, económicas, con menos características, pero más pisos.
  • Clúster 3: Viviendas con características intermedias en términos de precio, área, y otras características.
# Ajusta 'variable1' y 'variable2' a las columnas que deseas visualizar
ggplot(data_num, aes(x = areaconst, y = preciom, color = cluster)) +
  geom_point(size = 2) +
  labs(title = "Area construida vs Precio por Clúster",
       x = "Area construida", y = "Precio") +
  theme_minimal()

Se puede evidenciar que a medida que aumenta el área construida de la vivienda, también se incrementa su precio.

5. Análisis de correspondencias

Se extraen las columnas categoricas “zona”, “estrato” y “tipo” en un nuevo conjunto de datos, al que se le aplica el Análisis de Correspondencias Múltiples (MCA), técnica de reducción de dimensionalidad para datos categóricos:

data_cat = bd_clean[, c("zona", "estrato", "tipo")]
data_cat$estrato = as.factor(data_cat$estrato)
glimpse(data_cat)
## Rows: 8,319
## Columns: 3
## $ zona    <chr> "Zona Oriente", "Zona Oriente", "Zona Oriente", "Zona Sur", "Z…
## $ estrato <fct> 3, 3, 3, 4, 5, 5, 4, 5, 5, 5, 6, 4, 5, 6, 4, 5, 5, 4, 5, 3, 3,…
## $ tipo    <chr> "Casa", "Casa", "Casa", "Casa", "Apartamento", "Apartamento", …
# Realizar MCA
mca_result = MCA(data_cat)

# Mapa factorial de las variables
fviz_mca_var(mca_result, 
             geom = "point", 
             repel = TRUE, 
             title = "Mapa Factorial de Variables")

# Mapa factorial de los individuos
fviz_mca_ind(mca_result, 
             geom = "point", 
             repel = TRUE, 
             title = "Mapa Factorial de Individuos")

De acuerdo con los resultados obtenidos, se evidencia un alta correspondencia entre las variables estrato y zona. Por otro lado, vemos que la variable tipo no presenta una correspondencia significativa en relación con las otras dos variables.

  • El estrato 6 se encuentra ubicado en la Zona Oeste
  • Los estratos 4 y 5 están ubicados principalmente en la Zona Sur y Norte
  • El estrato 3 está presente en las Zonas Oriente y Centro
  • En las zonas centro, oriente y norte hay mayor presencia de vivienta tipo casa
  • En las zonas oeste y sur predomina la vivienda tipo apartamento

Conclusiones

El análisis de componentes principales ofrece una visión clara sobre el estado de las viviendas al correlacionar diversas variables numéricas, especialmente aquellas relacionadas con los precios. Esto ayuda a identificar qué variables influyen más en los valores de las viviendas.

El análisis de conglomerados complementa este enfoque al segmentar las viviendas en grupos similares, lo que facilita a la empresa la identificación de nichos de mercado y la definición de metas específicas. Aunque hay margen para profundizar, el análisis actual ya proporciona una comprensión útil de las viviendas en oferta y sus características.

Por otro lado, el análisis de correspondencias es limitado al trabajar con solo dos variables y puede no ser adecuado con un gran número de categorías. Sin embargo, revela relaciones entre variables categóricas y facilita el análisis al responder preguntas específicas sobre las viviendas.