INTRODUCCIÓN

En el contexto actual del mercado inmobiliario urbano, la toma de decisiones estratégicas requiere un conocimiento profundo y detallado de las dinámicas de oferta y demanda de viviendas. Una empresa inmobiliaria líder en una gran ciudad busca optimizar sus estrategias de compra, venta y valoración de propiedades mediante el análisis sistemático de su amplia base de datos, que contiene información exhaustiva sobre diversas propiedades residenciales disponibles en el mercado.

El presente estudio tiene como objetivo realizar un análisis holístico de esta base de datos, aplicando técnicas avanzadas de minería de datos y análisis estadístico para identificar patrones, relaciones y segmentaciones relevantes. Para ello, se contempla un proceso inicial de limpieza de datos, garantizando la calidad, coherencia y completitud de la información. Posteriormente, se aplicarán métodos analíticos complementarios:

Análisis de Componentes Principales (ACP): Se reducirá la dimensionalidad del conjunto de datos, permitiendo visualizar la estructura de las variables y determinar cuáles son las características clave que influyen en la variación de precios y en la disponibilidad de propiedades en el mercado.

Análisis de Conglomerados: Se agruparán las propiedades en segmentos homogéneos según sus características, facilitando la comprensión de las dinámicas específicas de oferta en diferentes zonas de la ciudad y estratos socioeconómicos.

Análisis de Correspondencia: Se explorarán las relaciones entre variables categóricas como tipo de vivienda, zona y barrio, con el fin de identificar patrones en el comportamiento del mercado y la preferencia de los consumidores.

Visualización de Resultados: Los hallazgos se presentarán mediante gráficos, mapas y otros recursos visuales que faciliten su interpretación y comunicación a la dirección de la empresa, apoyando así la toma de decisiones estratégicas basadas en evidencia.

Este enfoque integral permitirá no solo caracterizar el mercado inmobiliario urbano de manera precisa, sino también ofrecer herramientas prácticas para la planificación estratégica y la optimización de la gestión de propiedades, fortaleciendo la posición competitiva de la empresa en el sector.

1 Limpieza de datos

summary (vivienda)
##        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

1.1 Datos Faltantes

# Calcular número de NA por columna
na_count <- sapply(vivienda, function(x) sum(is.na(x)))

# Calcular porcentaje de NA
na_percent <- round(na_count / nrow(vivienda) * 100, 2)

# Convertir a data.frame para mostrar como tabla
tabla_na <- data.frame(
  variable = names(na_percent),
  porcentaje_NA = na_percent
)

# Mostrar tabla
tabla_na
##                  variable porcentaje_NA
## id                     id          0.04
## zona                 zona          0.04
## piso                 piso         31.70
## estrato           estrato          0.04
## preciom           preciom          0.02
## areaconst       areaconst          0.04
## parqueaderos parqueaderos         19.29
## banios             banios          0.04
## habitaciones habitaciones          0.04
## tipo                 tipo          0.04
## barrio             barrio          0.04
## longitud         longitud          0.04
## latitud           latitud          0.04
# Instalar ggplot2 si no lo tienes
# install.packages("ggplot2")
library(ggplot2)

ggplot(tabla_na, aes(x = reorder(variable, -porcentaje_NA), y = porcentaje_NA)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(title = "Porcentaje de Datos Faltantes por Variable",
       x = "Variable",
       y = "Porcentaje de NA (%)") +
  theme_minimal() +
  coord_flip()  # opcional: barras horizontales para mejor lectura

library(mice)
## 
## Adjuntando el paquete: 'mice'
## The following object is masked from 'package:stats':
## 
##     filter
## The following objects are masked from 'package:base':
## 
##     cbind, rbind
# Seleccionar solo las variables piso y parqueaderos
datos_sub <- vivienda[, c("piso", "parqueaderos")]

# Revisar cantidad de NA por variable
colSums(is.na(datos_sub))
##         piso parqueaderos 
##         2638         1605
# Realizar imputación múltiple
imputacion <- mice(datos_sub, m = 5, maxit = 50, seed = 123)
## 
##  iter imp variable
##   1   1  parqueaderos
##   1   2  parqueaderos
##   1   3  parqueaderos
##   1   4  parqueaderos
##   1   5  parqueaderos
##   2   1  parqueaderos
##   2   2  parqueaderos
##   2   3  parqueaderos
##   2   4  parqueaderos
##   2   5  parqueaderos
##   3   1  parqueaderos
##   3   2  parqueaderos
##   3   3  parqueaderos
##   3   4  parqueaderos
##   3   5  parqueaderos
##   4   1  parqueaderos
##   4   2  parqueaderos
##   4   3  parqueaderos
##   4   4  parqueaderos
##   4   5  parqueaderos
##   5   1  parqueaderos
##   5   2  parqueaderos
##   5   3  parqueaderos
##   5   4  parqueaderos
##   5   5  parqueaderos
##   6   1  parqueaderos
##   6   2  parqueaderos
##   6   3  parqueaderos
##   6   4  parqueaderos
##   6   5  parqueaderos
##   7   1  parqueaderos
##   7   2  parqueaderos
##   7   3  parqueaderos
##   7   4  parqueaderos
##   7   5  parqueaderos
##   8   1  parqueaderos
##   8   2  parqueaderos
##   8   3  parqueaderos
##   8   4  parqueaderos
##   8   5  parqueaderos
##   9   1  parqueaderos
##   9   2  parqueaderos
##   9   3  parqueaderos
##   9   4  parqueaderos
##   9   5  parqueaderos
##   10   1  parqueaderos
##   10   2  parqueaderos
##   10   3  parqueaderos
##   10   4  parqueaderos
##   10   5  parqueaderos
##   11   1  parqueaderos
##   11   2  parqueaderos
##   11   3  parqueaderos
##   11   4  parqueaderos
##   11   5  parqueaderos
##   12   1  parqueaderos
##   12   2  parqueaderos
##   12   3  parqueaderos
##   12   4  parqueaderos
##   12   5  parqueaderos
##   13   1  parqueaderos
##   13   2  parqueaderos
##   13   3  parqueaderos
##   13   4  parqueaderos
##   13   5  parqueaderos
##   14   1  parqueaderos
##   14   2  parqueaderos
##   14   3  parqueaderos
##   14   4  parqueaderos
##   14   5  parqueaderos
##   15   1  parqueaderos
##   15   2  parqueaderos
##   15   3  parqueaderos
##   15   4  parqueaderos
##   15   5  parqueaderos
##   16   1  parqueaderos
##   16   2  parqueaderos
##   16   3  parqueaderos
##   16   4  parqueaderos
##   16   5  parqueaderos
##   17   1  parqueaderos
##   17   2  parqueaderos
##   17   3  parqueaderos
##   17   4  parqueaderos
##   17   5  parqueaderos
##   18   1  parqueaderos
##   18   2  parqueaderos
##   18   3  parqueaderos
##   18   4  parqueaderos
##   18   5  parqueaderos
##   19   1  parqueaderos
##   19   2  parqueaderos
##   19   3  parqueaderos
##   19   4  parqueaderos
##   19   5  parqueaderos
##   20   1  parqueaderos
##   20   2  parqueaderos
##   20   3  parqueaderos
##   20   4  parqueaderos
##   20   5  parqueaderos
##   21   1  parqueaderos
##   21   2  parqueaderos
##   21   3  parqueaderos
##   21   4  parqueaderos
##   21   5  parqueaderos
##   22   1  parqueaderos
##   22   2  parqueaderos
##   22   3  parqueaderos
##   22   4  parqueaderos
##   22   5  parqueaderos
##   23   1  parqueaderos
##   23   2  parqueaderos
##   23   3  parqueaderos
##   23   4  parqueaderos
##   23   5  parqueaderos
##   24   1  parqueaderos
##   24   2  parqueaderos
##   24   3  parqueaderos
##   24   4  parqueaderos
##   24   5  parqueaderos
##   25   1  parqueaderos
##   25   2  parqueaderos
##   25   3  parqueaderos
##   25   4  parqueaderos
##   25   5  parqueaderos
##   26   1  parqueaderos
##   26   2  parqueaderos
##   26   3  parqueaderos
##   26   4  parqueaderos
##   26   5  parqueaderos
##   27   1  parqueaderos
##   27   2  parqueaderos
##   27   3  parqueaderos
##   27   4  parqueaderos
##   27   5  parqueaderos
##   28   1  parqueaderos
##   28   2  parqueaderos
##   28   3  parqueaderos
##   28   4  parqueaderos
##   28   5  parqueaderos
##   29   1  parqueaderos
##   29   2  parqueaderos
##   29   3  parqueaderos
##   29   4  parqueaderos
##   29   5  parqueaderos
##   30   1  parqueaderos
##   30   2  parqueaderos
##   30   3  parqueaderos
##   30   4  parqueaderos
##   30   5  parqueaderos
##   31   1  parqueaderos
##   31   2  parqueaderos
##   31   3  parqueaderos
##   31   4  parqueaderos
##   31   5  parqueaderos
##   32   1  parqueaderos
##   32   2  parqueaderos
##   32   3  parqueaderos
##   32   4  parqueaderos
##   32   5  parqueaderos
##   33   1  parqueaderos
##   33   2  parqueaderos
##   33   3  parqueaderos
##   33   4  parqueaderos
##   33   5  parqueaderos
##   34   1  parqueaderos
##   34   2  parqueaderos
##   34   3  parqueaderos
##   34   4  parqueaderos
##   34   5  parqueaderos
##   35   1  parqueaderos
##   35   2  parqueaderos
##   35   3  parqueaderos
##   35   4  parqueaderos
##   35   5  parqueaderos
##   36   1  parqueaderos
##   36   2  parqueaderos
##   36   3  parqueaderos
##   36   4  parqueaderos
##   36   5  parqueaderos
##   37   1  parqueaderos
##   37   2  parqueaderos
##   37   3  parqueaderos
##   37   4  parqueaderos
##   37   5  parqueaderos
##   38   1  parqueaderos
##   38   2  parqueaderos
##   38   3  parqueaderos
##   38   4  parqueaderos
##   38   5  parqueaderos
##   39   1  parqueaderos
##   39   2  parqueaderos
##   39   3  parqueaderos
##   39   4  parqueaderos
##   39   5  parqueaderos
##   40   1  parqueaderos
##   40   2  parqueaderos
##   40   3  parqueaderos
##   40   4  parqueaderos
##   40   5  parqueaderos
##   41   1  parqueaderos
##   41   2  parqueaderos
##   41   3  parqueaderos
##   41   4  parqueaderos
##   41   5  parqueaderos
##   42   1  parqueaderos
##   42   2  parqueaderos
##   42   3  parqueaderos
##   42   4  parqueaderos
##   42   5  parqueaderos
##   43   1  parqueaderos
##   43   2  parqueaderos
##   43   3  parqueaderos
##   43   4  parqueaderos
##   43   5  parqueaderos
##   44   1  parqueaderos
##   44   2  parqueaderos
##   44   3  parqueaderos
##   44   4  parqueaderos
##   44   5  parqueaderos
##   45   1  parqueaderos
##   45   2  parqueaderos
##   45   3  parqueaderos
##   45   4  parqueaderos
##   45   5  parqueaderos
##   46   1  parqueaderos
##   46   2  parqueaderos
##   46   3  parqueaderos
##   46   4  parqueaderos
##   46   5  parqueaderos
##   47   1  parqueaderos
##   47   2  parqueaderos
##   47   3  parqueaderos
##   47   4  parqueaderos
##   47   5  parqueaderos
##   48   1  parqueaderos
##   48   2  parqueaderos
##   48   3  parqueaderos
##   48   4  parqueaderos
##   48   5  parqueaderos
##   49   1  parqueaderos
##   49   2  parqueaderos
##   49   3  parqueaderos
##   49   4  parqueaderos
##   49   5  parqueaderos
##   50   1  parqueaderos
##   50   2  parqueaderos
##   50   3  parqueaderos
##   50   4  parqueaderos
##   50   5  parqueaderos
## Warning: Number of logged events: 1
# Resumen de la imputación
summary(imputacion)
## Class: mids
## Number of multiple imputations:  5 
## Imputation methods:
##         piso parqueaderos 
##           ""        "pmm" 
## PredictorMatrix:
##              piso parqueaderos
## piso            0            0
## parqueaderos    0            0
## Number of logged events:  1 
##   it im dep     meth  out
## 1  0  0     constant piso
# Extraer dataset imputado completo (primer imputado)
datos_imputados <- complete(imputacion, 1)

# Reemplazar las columnas originales en vivienda con las imputadas
vivienda$piso <- datos_imputados$piso
vivienda$parqueaderos <- datos_imputados$parqueaderos

# Verificar que ya no haya NA en esas columnas
colSums(is.na(vivienda[, c("piso", "parqueaderos")]))
##         piso parqueaderos 
##         2638            0
library(mice)

# Seleccionar solo las variables piso y parqueaderos
datos_sub <- vivienda[, c("piso", "parqueaderos")]

# Revisar cantidad de NA por variable
colSums(is.na(datos_sub))
##         piso parqueaderos 
##         2638            0
# Realizar imputación múltiple
imputacion <- mice(datos_sub, m = 5, maxit = 50, seed = 123)
## 
##  iter imp variable
##   1   1
##   1   2
##   1   3
##   1   4
##   1   5
##   2   1
##   2   2
##   2   3
##   2   4
##   2   5
##   3   1
##   3   2
##   3   3
##   3   4
##   3   5
##   4   1
##   4   2
##   4   3
##   4   4
##   4   5
##   5   1
##   5   2
##   5   3
##   5   4
##   5   5
##   6   1
##   6   2
##   6   3
##   6   4
##   6   5
##   7   1
##   7   2
##   7   3
##   7   4
##   7   5
##   8   1
##   8   2
##   8   3
##   8   4
##   8   5
##   9   1
##   9   2
##   9   3
##   9   4
##   9   5
##   10   1
##   10   2
##   10   3
##   10   4
##   10   5
##   11   1
##   11   2
##   11   3
##   11   4
##   11   5
##   12   1
##   12   2
##   12   3
##   12   4
##   12   5
##   13   1
##   13   2
##   13   3
##   13   4
##   13   5
##   14   1
##   14   2
##   14   3
##   14   4
##   14   5
##   15   1
##   15   2
##   15   3
##   15   4
##   15   5
##   16   1
##   16   2
##   16   3
##   16   4
##   16   5
##   17   1
##   17   2
##   17   3
##   17   4
##   17   5
##   18   1
##   18   2
##   18   3
##   18   4
##   18   5
##   19   1
##   19   2
##   19   3
##   19   4
##   19   5
##   20   1
##   20   2
##   20   3
##   20   4
##   20   5
##   21   1
##   21   2
##   21   3
##   21   4
##   21   5
##   22   1
##   22   2
##   22   3
##   22   4
##   22   5
##   23   1
##   23   2
##   23   3
##   23   4
##   23   5
##   24   1
##   24   2
##   24   3
##   24   4
##   24   5
##   25   1
##   25   2
##   25   3
##   25   4
##   25   5
##   26   1
##   26   2
##   26   3
##   26   4
##   26   5
##   27   1
##   27   2
##   27   3
##   27   4
##   27   5
##   28   1
##   28   2
##   28   3
##   28   4
##   28   5
##   29   1
##   29   2
##   29   3
##   29   4
##   29   5
##   30   1
##   30   2
##   30   3
##   30   4
##   30   5
##   31   1
##   31   2
##   31   3
##   31   4
##   31   5
##   32   1
##   32   2
##   32   3
##   32   4
##   32   5
##   33   1
##   33   2
##   33   3
##   33   4
##   33   5
##   34   1
##   34   2
##   34   3
##   34   4
##   34   5
##   35   1
##   35   2
##   35   3
##   35   4
##   35   5
##   36   1
##   36   2
##   36   3
##   36   4
##   36   5
##   37   1
##   37   2
##   37   3
##   37   4
##   37   5
##   38   1
##   38   2
##   38   3
##   38   4
##   38   5
##   39   1
##   39   2
##   39   3
##   39   4
##   39   5
##   40   1
##   40   2
##   40   3
##   40   4
##   40   5
##   41   1
##   41   2
##   41   3
##   41   4
##   41   5
##   42   1
##   42   2
##   42   3
##   42   4
##   42   5
##   43   1
##   43   2
##   43   3
##   43   4
##   43   5
##   44   1
##   44   2
##   44   3
##   44   4
##   44   5
##   45   1
##   45   2
##   45   3
##   45   4
##   45   5
##   46   1
##   46   2
##   46   3
##   46   4
##   46   5
##   47   1
##   47   2
##   47   3
##   47   4
##   47   5
##   48   1
##   48   2
##   48   3
##   48   4
##   48   5
##   49   1
##   49   2
##   49   3
##   49   4
##   49   5
##   50   1
##   50   2
##   50   3
##   50   4
##   50   5
## Warning: Number of logged events: 1
# Resumen de la imputación
summary(imputacion)
## Class: mids
## Number of multiple imputations:  5 
## Imputation methods:
##         piso parqueaderos 
##           ""           "" 
## PredictorMatrix:
##              piso parqueaderos
## piso            0            0
## parqueaderos    0            0
## Number of logged events:  1 
##   it im dep     meth  out
## 1  0  0     constant piso
# Extraer dataset imputado completo (primer imputado)
datos_imputados <- complete(imputacion, 1)

# Reemplazar las columnas originales en vivienda con las imputadas
vivienda$piso <- datos_imputados$piso
vivienda$parqueaderos <- datos_imputados$parqueaderos

# Verificar que ya no haya NA en esas columnas
colSums(is.na(vivienda[, c("piso", "parqueaderos")]))
##         piso parqueaderos 
##         2638            0
# Renombrar la base completa como df
df <- vivienda

# Verificación rápida
head(df)
## # A tibble: 6 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1147 Zona O… <NA>        3     250        70            1      3            6
## 2  1169 Zona O… <NA>        3     320       120            1      2            3
## 3  1350 Zona O… <NA>        3     350       220            2      2            4
## 4  5992 Zona S… 02          4     400       280            3      5            3
## 5  1212 Zona N… 01          5     260        90            1      2            3
## 6  1724 Zona N… 01          5     240        87            1      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
summary(df)
##        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.904   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   :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
# Eliminar todas las filas con NA
df <- na.omit(df)

# Verificar que no queden NAs
colSums(is.na(df))
##           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

Después de aplicar la técnica de imputación múltiple a las variables piso y parqueaderos, se logró reemplazar los valores faltantes en estas columnas de manera estadísticamente consistente, preservando la estructura y distribución de los datos originales. Esto permitió que estas variables ya no contengan NAs, lo que mejora la calidad y la integridad del dataset. Los datos faltantes restantes en otras variables representan porcentajes mínimos, por lo que se decidió eliminarlos, asegurando que el análisis posterior se realice sobre un conjunto de datos completo sin comprometer la representatividad de la información. Esto facilita los análisis estadísticos y la modelación, evitando sesgos derivados de la falta de datos.

1.2 Outlier´s

library(ggplot2)
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.5.2
## 
## Adjuntando el paquete: 'dplyr'
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyr)
## Warning: package 'tidyr' was built under R version 4.5.2
# Variables a excluir
vars_excluidas <- c("id", "latitud", "longitud", "estrato")

# Seleccionar variables numéricas y excluir las mencionadas
numericas <- df %>% 
  select(where(is.numeric)) %>% 
  select(-all_of(vars_excluidas))

# Transformar a formato largo para ggplot
datos_largos <- numericas %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor")

# Crear diagrama de caja profesional
ggplot(datos_largos, aes(x = Variable, y = Valor)) +
  geom_boxplot(fill = "#69b3a2", color = "#1f3552", outlier.color = "red", outlier.shape = 16) +
  theme_minimal(base_size = 14) +
  labs(title = "Diagrama de caja de variables numéricas seleccionadas",
       x = "Variable",
       y = "Valor") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

El análisis del diagrama de cajas evidencia una presencia considerable de valores atípicos, especialmente en las variables de mayor magnitud como precio y área construida, donde se observa una marcada asimetría positiva y una dispersión amplia en la parte superior de la distribución. Estos valores extremos pueden influir de manera desproporcionada en las medidas estadísticas y afectar la estabilidad de futuros modelos predictivos. No obstante, dado que en el contexto inmobiliario los valores elevados pueden corresponder a propiedades de alto valor y no necesariamente a errores, no resulta adecuado eliminarlos directamente. Por esta razón, el tratamiento se llevará únicamente hasta la aplicación de una Winsorización Profesional basada en los percentiles 1% y 99%, técnica que permite limitar los valores extremadamente bajos y altos reemplazándolos por los puntos de corte definidos en dichos percentiles. Con ello se reduce la influencia de los extremos, se mantiene la integridad del conjunto de datos y se mejora la robustez del análisis sin perder observaciones.

library(dplyr)
library(tidyr)
library(ggplot2)

# Variables a excluir
vars_excluidas <- c("id", "latitud", "longitud", "estrato")

# Función para winsorizar con percentiles 1% y 99%
winsorize_percentile <- function(x, lower = 0.01, upper = 0.99) {
  lower_bound <- quantile(x, lower, na.rm = TRUE)
  upper_bound <- quantile(x, upper, na.rm = TRUE)
  x[x < lower_bound] <- lower_bound
  x[x > upper_bound] <- upper_bound
  return(x)
}

# Selección variables numéricas excluyendo las indicadas
numericas <- df %>% 
  select(where(is.numeric)) %>% 
  select(-all_of(vars_excluidas))

# Transformar con log(x + 1) para evitar problemas con ceros
df_log <- numericas %>%
  mutate(across(everything(), ~ log(.x + 1)))

# Aplicar winsorización a las variables transformadas
df_log_w <- df_log %>%
  mutate(across(everything(), ~ winsorize_percentile(.x)))

# Preparar datos para graficar
df_long <- df_log_w %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor")

# Graficar boxplot profesional
ggplot(df_long, aes(x = Variable, y = Valor, fill = Variable)) +
  geom_boxplot(alpha = 0.8, outlier.color = "red", outlier.shape = 16, outlier.size = 2) +
  labs(
    title = "Boxplot de variables numéricas log-transformadas y winsorizadas",
    x = "Variable",
    y = "Valor (log-transformado y winsorizado)"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "none",
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5)
  )

library(dplyr)
library(tidyr)
library(ggplot2)

# Variables a excluir
vars_excluidas <- c("id", "latitud", "longitud", "estrato")

# Función para winsorizar con percentiles 5% y 95%
winsorize_percentile <- function(x, lower = 0.05, upper = 0.95) {
  lower_bound <- quantile(x, lower, na.rm = TRUE)
  upper_bound <- quantile(x, upper, na.rm = TRUE)
  x[x < lower_bound] <- lower_bound
  x[x > upper_bound] <- upper_bound
  return(x)
}

# Selección variables numéricas excluyendo las indicadas
numericas <- df %>% 
  select(where(is.numeric)) %>% 
  select(-all_of(vars_excluidas))

# Transformar con log(x + 1) para evitar problemas con ceros
df_log <- numericas %>%
  mutate(across(everything(), ~ log(.x + 1)))

# Aplicar winsorización más fuerte (5% y 95%) a todas las variables transformadas
df_log_w <- df_log %>%
  mutate(across(everything(), ~ winsorize_percentile(.x)))

# Preparar datos para graficar (formato largo)
df_long <- df_log_w %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor")

# Graficar boxplot profesional
ggplot(df_long, aes(x = Variable, y = Valor, fill = Variable)) +
  geom_boxplot(alpha = 0.8, outlier.color = "red", outlier.shape = 16, outlier.size = 2) +
  labs(
    title = "Boxplot de variables numéricas log-transformadas y winsorizadas (5% - 95%)",
    x = "Variable",
    y = "Valor (log-transformado y winsorizado)"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "none",
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5)
  )

Winsorización más fuerte usando los percentiles 5% y 95% a todas las variables log-transformadas.

library(dplyr)
library(tidyr)
library(ggplot2)

# Variables a excluir
vars_excluidas <- c("id", "latitud", "longitud", "estrato")

# Función para winsorizar con percentiles 5% y 95%
winsorize_percentile <- function(x, lower = 0.05, upper = 0.95) {
  lower_bound <- quantile(x, lower, na.rm = TRUE)
  upper_bound <- quantile(x, upper, na.rm = TRUE)
  x[x < lower_bound] <- lower_bound
  x[x > upper_bound] <- upper_bound
  return(x)
}

# Selección variables numéricas excluyendo las indicadas
numericas <- df %>% 
  select(where(is.numeric)) %>% 
  select(-all_of(vars_excluidas))

# Transformar con log(x + 1) para evitar problemas con ceros
df_log <- numericas %>%
  mutate(across(everything(), ~ log(.x + 1)))

# Aplicar winsorización más fuerte (5% y 95%) a todas las variables transformadas
df_log_w <- df_log %>%
  mutate(across(everything(), ~ winsorize_percentile(.x)))

# Preparar datos para graficar (formato largo)
df_long <- df_log_w %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor")

# Graficar boxplot profesional
ggplot(df_long, aes(x = Variable, y = Valor, fill = Variable)) +
  geom_boxplot(alpha = 0.8, outlier.color = "red", outlier.shape = 16, outlier.size = 2) +
  labs(
    title = "Boxplot de variables numéricas log-transformadas y winsorizadas (5% - 95%)",
    x = "Variable",
    y = "Valor (log-transformado y winsorizado)"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "none",
    plot.title = element_text(face = "bold", size = 12, hjust = 0.5)
  )

La winsorización previa aplicada con percentiles 1% y 99% no fue suficientemente efectiva para controlar los valores atípicos en algunas variables, especialmente en las que presentaban una mayor dispersión o datos extremos. Estos valores atípicos persistentes pueden distorsionar el análisis posterior, como el PCA, afectando la interpretación y la estabilidad de los componentes principales. Por ello, se aplicó una winsorización más fuerte con percentiles 5% y 95%, lo que reduce más agresivamente los valores extremos y ayuda a normalizar la distribución de las variables. Esto mejora la calidad de los datos y la robustez del análisis multivariante subsiguiente.

2 PCA (Análisis de Componentes Principales)

# Librerías necesarias
library(dplyr)
library(ggplot2)
library(tidyr)
library(FactoMineR)   # Para PCA profesional
## Warning: package 'FactoMineR' was built under R version 4.5.2
library(factoextra)   # Para visualización de PCA
## Warning: package 'factoextra' was built under R version 4.5.2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
# 1. Preparar los datos
# Usamos df_log_w que ya está log-transformado y winsorizado
pca_data <- df_log_w

# Escalar las variables (muy importante para PCA)
pca_data_scaled <- scale(pca_data)

# 2. Aplicar PCA
pca_res <- PCA(pca_data_scaled, graph = FALSE)

# 3. Resumen de varianza explicada
eig_val <- get_eigenvalue(pca_res)
print(eig_val)
##       eigenvalue variance.percent cumulative.variance.percent
## Dim.1  3.3630647        67.261294                    67.26129
## Dim.2  0.7724422        15.448845                    82.71014
## Dim.3  0.4997020         9.994041                    92.70418
## Dim.4  0.2404164         4.808327                    97.51251
## Dim.5  0.1243746         2.487493                   100.00000
# 4. Graficar varianza explicada (scree plot)
fviz_eig(pca_res, addlabels = TRUE, ylim = c(0, 60)) +
  ggtitle("Scree Plot: Varianza explicada por cada componente") +
  theme_minimal()
## Warning in geom_bar(stat = "identity", fill = barfill, color = barcolor, :
## Ignoring empty aesthetic: `width`.

# 5. Graficar el plano de componentes (PC1 vs PC2)
fviz_pca_ind(pca_res,
             geom.ind = "point", # puntos de individuos
             col.ind = "blue",   # color de los puntos
             addEllipses = TRUE, # elipses de confianza
             ellipse.level = 0.95,
             repel = TRUE) +
  ggtitle("Plano de Componentes Principales (PC1 vs PC2)") +
  theme_minimal()

# 6. Graficar variables (contribución a PC1 y PC2)
fviz_pca_var(pca_res,
             col.var = "contrib", # color según contribución
             gradient.cols = c("lightblue", "blue", "darkblue"),
             repel = TRUE) +
  ggtitle("Contribución de las variables al PCA") +
  theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## ℹ The deprecated feature was likely used in the ggpubr package.
##   Please report the issue at <https://github.com/kassambara/ggpubr/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the factoextra package.
##   Please report the issue at <https://github.com/kassambara/factoextra/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

El análisis de componentes principales (PCA) realizado sobre la base de datos de propiedades residenciales (tras aplicar transformación logarítmica +1 y winsorización al 5%-95% para estabilizar distribuciones y mitigar el impacto de valores extremos típicos en variables inmobiliarias como precio, área o número de habitaciones) proporciona una visión clara y reducida de la estructura subyacente del mercado de viviendas urbanas. Resumen de la varianza explicada (Scree Plot)

2.0.1 El scree plot

muestra una caída pronunciada después del primer componente, lo cual es típico en conjuntos inmobiliarios donde existe una fuerte dimensión dominante.

Dim1 (PC1): explica 67.3% de la varianza total, representa la principal “dirección” de diferenciación en el mercado. Dim2 (PC2): explica 15.4% adicional, captura una segunda fuente importante de variabilidad, ortogonal a la primera.

Juntas, Dim1 + Dim2 explican ≈ 82.7% de la varianza total de las variables numéricas consideradas (excluyendo identificadores, coordenadas geográficas y estrato). Las dimensiones subsiguientes aportan cantidades marginales (10%, 4.8%, 2.5%…), lo que justifica enfocarse principalmente en las dos primeras componentes para interpretación y modelado estratégico.

Esto indica que el mercado puede describirse de manera muy eficiente con solo dos dimensiones sintéticas, reteniendo la gran mayoría de la información relevante y eliminando ruido/redundancia.

2.0.2 Interpretación del círculo de contribuciones / correlaciones (variable contribution plot)

El gráfico muestra las variables proyectadas en el espacio de las dos primeras componentes (círculo de correlación o contribución), con vectores que indican dirección y magnitud de su relación con Dim1 y Dim2. El color (escala azul) refleja la contribución aproximada de cada variable al plano formado por PC1 y PC2 (valores entre ~19.5% y 21%). Las variables se agrupan claramente en dos patrones opuestos:

Dimensión 1 (horizontal, 67.3%) – Eje principal de “tamaño / confort / valor” Variables con cargas positivas fuertes hacia la derecha: parqueaderos (flecha larga hacia arriba-derecha) habitaciones baños → Esta dimensión captura principalmente el tamaño y nivel de equipamiento de la vivienda (número de habitaciones, baños y plazas de parqueo). Es muy probable que esté altamente correlacionada con el precio de venta o arriendo, el área construida y el estándar general de la propiedad. En el contexto inmobiliario urbano, representa el eje de calidad / amplitud / valor percibido de la vivienda.

Dimensión 2 (vertical, 15.4%) – Eje secundario de “costos asociados / mantenimiento” Variables con cargas negativas leves hacia abajo: preciom (probablemente precio del metro cuadrado o similar) arcacons / arcacont (área construida o área constante/privada) → Esta dimensión parece diferenciar propiedades con alta densidad de valor por m² (preciom alto, posiblemente apartamentos más pequeños pero en zonas premium) versus propiedades con mayor área total pero menor precio por unidad de superficie.

La proximidad entre preciom y arcacons sugiere que, una vez controlado el tamaño general (Dim1), existe una trade-off entre área y precio unitario.

La variable parqueaderos destaca como la de mayor proyección y contribución en el cuadrante positivo, lo que subraya su rol clave como diferenciador de valor en el mercado urbano analizado (muy común en ciudades con alta congestión y escasez de estacionamiento).

2.0.3 Conclusiones y recomendaciones estratégicas para la empresa inmobiliaria

El mercado residencial urbano está dominado por una única dimensión principal (~67%) relacionada con el tamaño, confort y equipamiento básico (habitaciones + baños + parqueaderos). Esto confirma que, en términos generales, “más grande y mejor equipado = mayor valor”, siendo el factor determinante en la mayoría de las decisiones de compra/venta. Una segunda dimensión (~15%) refleja eficiencia de precio por m² vs. área total, lo que permite distinguir segmentos de mercado: Propiedades grandes y con muchos parqueaderos/baños/habitaciones (alta Dim1) segmento familiar o de mayor valor absoluto. Propiedades con alto preciom² pero menor área o menos equipamiento segmento premium/compacto (posiblemente en zonas céntricas o de alta demanda).

2.0.4 Implicaciones prácticas:

Segmentación: Utilizar las dos primeras componentes como base para clustering (k-means, jerárquico, etc.) y crear perfiles claros de propiedades (ej. “amplias familiares con parqueo”, “compactas premium alto m²”, etc.). Valoración: Modelos de regresión o machine learning que incluyan PC1 y PC2 como predictores capturarán la mayor parte de la variabilidad de precio con menos riesgo de multicolinealidad. Estrategia comercial: Priorizar la captación y promoción de propiedades con alto número de parqueaderos, ya que esta variable aparece como la más discriminante y contribuyente en el plano principal. Próximos pasos: Incorporar variables categóricas (estrato, zona, tipo de propiedad) mediante PCA mixto o análisis factorial múltiple, y explorar la relación de las componentes con el precio objetivo mediante correlaciones o regresión.

En síntesis, el PCA revela un mercado estructurado en torno a tamaño/confort como driver principal y eficiencia de precio por superficie como driver secundario, ofreciendo una base sólida y simplificada para segmentar, valorar y tomar decisiones estratégicas en el competitivo entorno inmobiliario urbano.

3 Análisis de Conglomerados (Cluster Analysis)

library(cluster)
## Warning: package 'cluster' was built under R version 4.5.2
library(factoextra)
library(ggplot2)
library(dplyr)

Los datos ya están preprocesados (log-transformados y winsorizados), lo cual es ideal para clustering ya que reduce el impacto de outliers y escala las variables. Verificamos la estructura y estandarizamos (escalamos a media 0 y varianza 1) para que todas las variables contribuyan equitativamente, ya que el clustering sensible a escalas (e.g., Euclidean distance).

# Asumiendo df_log_w del procesamiento anterior
head(df_log_w)  # Inspecciona las primeras filas
## # A tibble: 6 × 5
##   preciom areaconst parqueaderos banios habitaciones
##     <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1    5.99      5.64        1.39    1.79         1.39
## 2    5.56      4.51        0.693   1.10         1.39
## 3    5.48      4.48        0.693   1.39         1.39
## 4    5.40      4.06        1.10    1.10         1.39
## 5    5.74      4.93        1.10    1.39         1.61
## 6    5.77      5.02        1.10    1.61         1.95
# Estandarizar los datos (centrado y escalado)
df_scaled <- scale(df_log_w)

# Verificar dimensiones (debe tener solo variables numéricas como habitaciones, baños, parqueaderos, etc.)
dim(df_scaled)
## [1] 5684    5
summary(df_scaled)
##     preciom           areaconst        parqueaderos         banios       
##  Min.   :-1.59514   Min.   :-1.3389   Min.   :-0.9920   Min.   :-2.0635  
##  1st Qu.:-0.70593   1st Qu.:-0.8384   1st Qu.:-0.9920   1st Qu.:-0.7904  
##  Median :-0.08459   Median :-0.1885   Median : 0.3491   Median : 0.1128  
##  Mean   : 0.00000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000  
##  3rd Qu.: 0.69771   3rd Qu.: 0.8056   3rd Qu.: 0.3491   3rd Qu.: 0.8134  
##  Max.   : 1.97805   Max.   : 1.9614   Max.   : 2.0386   Max.   : 1.8699  
##   habitaciones    
##  Min.   :-1.6421  
##  1st Qu.:-0.3757  
##  Median :-0.3757  
##  Mean   : 0.0000  
##  3rd Qu.: 0.6066  
##  Max.   : 2.0878

Usamos distancia Euclidiana, común para datos continuos inmobiliarios, ya que mide similitud geométrica.

# Calcular matriz de distancias Euclidiana
dist_matrix <- dist(df_scaled, method = "euclidean")
# Realizar clustering jerárquico
hc_model <- hclust(dist_matrix, method = "ward.D2")

# Visualizar dendrograma
plot(hc_model, main = "Dendrograma de Clustering Jerárquico (Ward)",
     xlab = "Propiedades", sub = NULL, hang = -1)
abline(h = 120, col = "red", lty = 2)  # Línea de corte de ejemplo; ajusta basado en próximo paso

# Método del codo (elbow): varianza intra-cluster vs. número de clusters
fviz_nbclust(df_scaled, FUN = hcut, method = "wss", k.max = 10) +
  labs(title = "Método del Codo para Clustering Jerárquico")

# Método de silueta: calidad de clusters
fviz_nbclust(df_scaled, FUN = hcut, method = "silhouette", k.max = 10) +
  labs(title = "Método de Silueta para Clustering Jerárquico")

El análisis de clustering jerárquico utilizando el método de Ward evidencia una estructura clara en los datos. El dendrograma muestra una separación marcada entre grandes grupos, el método del codo sugiere un punto de inflexión alrededor de tres clusters, mientras que el índice de Silhouette alcanza su valor máximo en k = 2, indicando que esta partición ofrece la mejor calidad de separación y cohesión interna. En conjunto, los resultados permiten concluir que la estructura natural de los datos es predominantemente binaria, aunque una solución de tres clusters puede considerarse como alternativa si se requiere mayor nivel de segmentación. Sin embargo, desde un criterio estrictamente estadístico y de robustez, la solución de dos clusters se presenta como la más consistente y estable.

# Corte del dendrograma (ajusta 'k' según Paso 4)
k_optimo <- 2  # Ejemplo; cámbialo basado en métricas
clusters_hc <- cutree(hc_model, k = k_optimo)

# Agregar clusters al dataframe original para interpretación
df_clustered <- cbind(df_log_w, cluster = as.factor(clusters_hc))

# Resumen por cluster
df_clustered %>%
  group_by(cluster) %>%
  summarise(across(everything(), list(mean = ~mean(., na.rm=TRUE), sd = ~sd(., na.rm=TRUE))))
## # A tibble: 2 × 11
##   cluster preciom_mean preciom_sd areaconst_mean areaconst_sd parqueaderos_mean
##   <fct>          <dbl>      <dbl>          <dbl>        <dbl>             <dbl>
## 1 1               6.36      0.473           5.51        0.421             1.18 
## 2 2               5.51      0.457           4.52        0.370             0.883
## # ℹ 5 more variables: parqueaderos_sd <dbl>, banios_mean <dbl>,
## #   banios_sd <dbl>, habitaciones_mean <dbl>, habitaciones_sd <dbl>
# Corte del dendrograma (ajusta 'k' según Paso 4)
k_optimo <- 2  # Ejemplo; cámbialo basado en métricas
clusters_hc <- cutree(hc_model, k = k_optimo)

# Agregar clusters al dataframe original
df_clustered <- cbind(df_log_w, cluster = as.factor(clusters_hc))

# Convertir todas las columnas a escala real (exp(.) - 1)
df_clustered_real <- df_clustered %>%
  mutate(across(where(is.numeric), ~exp(.) - 1))  # revierte log(x+1) a escala real

# Resumen por cluster en escala real
library(dplyr)
df_clustered_real %>%
  group_by(cluster) %>%
  summarise(across(
    everything(), 
    list(mean = ~mean(., na.rm = TRUE), sd = ~sd(., na.rm = TRUE))
  ))
## # A tibble: 2 × 11
##   cluster preciom_mean preciom_sd areaconst_mean areaconst_sd parqueaderos_mean
##   <fct>          <dbl>      <dbl>          <dbl>        <dbl>             <dbl>
## 1 1               640.       293.          267.         105.               2.39
## 2 2               273.       139.           97.9         46.0              1.50
## # ℹ 5 more variables: parqueaderos_sd <dbl>, banios_mean <dbl>,
## #   banios_sd <dbl>, habitaciones_mean <dbl>, habitaciones_sd <dbl>

Después del análisis de clustering jerárquico, se identificaron dos grupos claros de propiedades. El Cluster 1 agrupa inmuebles de gama alta, con precios promedio de 640, áreas construidas de aproximadamente 267 m², 2-3 parqueaderos, más de 4 baños y alrededor de 4 a 5 habitaciones, mostrando mayor variabilidad entre sus características. En contraste, el Cluster 2 corresponde a propiedades más pequeñas y económicas, con precios promedio de 273, áreas de cerca de 98 m², 1-2 parqueaderos, aproximadamente 2 baños y 3 habitaciones, reflejando un perfil más homogéneo. Estos resultados, presentados en escala real, permiten interpretar de manera directa las diferencias en tamaño, precio y comodidades, facilitando la segmentación del mercado y la toma de decisiones estratégicas.

4 Analisis de Correspondecia

# Seleccionar solo variables categóricas
df_cat <- df[, c("barrio", "estrato", "zona")]

# Crear tabla de contingencia
tab_cont <- table(df_cat$zona, df_cat$estrato); tab_cont
##               
##                   3    4    5    6
##   Zona Centro    61    8    0    0
##   Zona Norte    318  231  505   85
##   Zona Oeste     36   64  192  513
##   Zona Oriente  199    7    2    0
##   Zona Sur      264 1206 1259  734

El análisis de correspondencia (Tabla de COntingencia) entre la zona y el estrato socioeconómico revela una asociación estructural clara entre ambas variables cualitativas. Las zonas Norte y Centro se relacionan principalmente con los estratos medios y altos (3, 4 y 5), lo que sugiere una concentración relativa de mejores condiciones socioeconómicas en estas áreas. En contraste, las zonas Sur y Oriente muestran una fuerte asociación con los estratos bajos (1 y 2), evidenciando patrones de segregación socioespacial. La zona Oeste presenta una distribución más heterogénea, aunque con predominio de estratos intermedios. En conjunto, los resultados confirman que la localización geográfica no es aleatoria respecto al estrato socioeconómico, sino que existe una correspondencia significativa que refleja desigualdades territoriales bien definidas.

library(FactoMineR)
library(factoextra)

# Crear tabla filtrando solo Norte, Oeste y Sur
tab_cont <- table(df$zona[df$zona %in% c("Zona Norte","Zona Oeste","Zona Sur")],
                  df$estrato[df$zona %in% c("Zona Norte","Zona Oeste","Zona Sur")])

# Eliminar filas o columnas vacías (aunque aquí todas tienen datos)
tab_cont <- tab_cont[rowSums(tab_cont) > 0, colSums(tab_cont) > 0]

# Análisis de Correspondencias
res_ca <- CA(tab_cont, graph = FALSE)

# Biplot
fviz_ca_biplot(res_ca, repel = TRUE,
               col.row = "blue",   # Zonas
               col.col = "red",    # Estratos
               title = "Biplot de Correspondencias: Zonas Norte, Oeste y Sur vs Estrato")

El biplot del análisis de correspondencias confirma una asociación estructural clara entre las zonas y los estratos socioeconómicos. La Dimensión 1 explica el 73.5% de la inercia total, por lo que concentra la mayor parte de la relación entre las variables, mientras que la Dimensión 2 (26.5%) complementa la diferenciación. Se observa que la Zona Norte se ubica próxima a los estratos medios y altos (especialmente 3 y 5), indicando una correspondencia positiva con niveles socioeconómicos superiores. La Zona Sur aparece más asociada a estratos intermedios-bajos, mientras que la Zona Oeste muestra afinidad con estratos específicos que la diferencian del resto, evidenciando patrones territoriales diferenciados. La separación espacial de los puntos en el plano factorial indica que la distribución del estrato no es homogénea entre zonas, sino que existe una segmentación socioespacial marcada, donde cada zona presenta un perfil socioeconómico característico.

5 CONCLUSIÓN GENERAL

A nivel integral, los resultados obtenidos mediante clustering jerárquico, análisis de correspondencias y análisis de componentes principales (PCA) son altamente consistentes y apuntan a una misma estructura latente en los datos. El PCA identifica dos componentes principales que explican el 82.7 % de la variabilidad total, lo que evidencia que la información esencial puede resumirse en un espacio de baja dimensión dominado por dos factores fundamentales. De manera concordante, el análisis de correspondencias muestra que la primera dimensión concentra la mayor parte de la inercia, revelando una oposición clara entre perfiles territoriales y socioeconómicos. Esta estructura casi dicotómica se ve reforzada por el clustering jerárquico, donde la solución de dos clusters presenta la mayor estabilidad y separación, mientras que una partición en tres clusters emerge como una subdivisión secundaria de uno de los grupos principales. En conjunto, estos resultados confirman la existencia de dos grandes perfiles estructurales bien definidos, con variaciones internas que pueden refinarse, pero sin alterar la organización fundamental de los datos, lo que otorga solidez estadística y coherencia interpretativa al análisis multivariado realizado.