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

Exploración de la base 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

Diemnsión de la base de datos

dimVivienda = dim(vivienda)
dimVivienda
## [1] 8322   13

Revision de datos faltantes

md.pattern(vivienda)

##      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

Inspeccion variables categoricas

A continuación revisaremos que las variables categóricas tengan los valores normalizados

table(vivienda$zona)
## 
##  Zona Centro   Zona Norte   Zona Oeste Zona Oriente     Zona Sur 
##          124         1920         1198          351         4726
table(vivienda$piso)
## 
##   01   02   03   04   05   06   07   08   09   10   11   12 
##  860 1450 1097  607  567  245  204  211  146  130   84   83
table(vivienda$estrato)
## 
##    3    4    5    6 
## 1453 2129 2750 1987
#table(vivienda$barrio)

Descripción de la base de datos

De la exploración de datos encontramos lo siguiente:

  • La base de datos tiene 13 variables y 8322 filas.
  • Cuatro variables categóricas zona, estrato, tipo y barrio.
  • Nueve variables numéricas id, areaconst, piso, habitaciones, banios, parqueaderos, preciom, latitud y longitud.
  • LA variable id que proporciona un identificador único para cada registro y que no aporta ninguna información relevante para el análisis.
  • Se puede observar que las variables categóricas están normalizadas, excepto por los barrios que se encuentran con mayúsculas y minúsculas, caracteres especiales, algunos con tilde y otros sin tilde.

Transformaciones

Eliminación de filas vacias

dfVivienda <- vivienda %>% filter(!is.na(id) & id != "")
colSums(is.na(dfVivienda))
##           id         zona         piso      estrato      preciom    areaconst 
##            0            0         2635            0            0            0 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##         1602            0            0            0            0            0 
##      latitud 
##            0
print(dim(dfVivienda))
## [1] 8319   13
md.pattern(dfVivienda)

##      id zona estrato preciom 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
##       0    0       0       0         0      0            0    0      0        0
##      latitud parqueaderos piso     
## 4808       1            1    1    0
## 1909       1            1    0    1
## 876        1            0    1    1
## 726        1            0    0    2
##            0         1602 2635 4237

Se eliman variables no relevantes

dfVivienda <- dfVivienda %>% dplyr::select(-id, -longitud, -latitud, -barrio)
dfVivienda
## # A tibble: 8,319 × 9
##    zona   piso  estrato preciom areaconst parqueaderos banios habitaciones tipo 
##    <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl> <chr>
##  1 Zona … <NA>        3     250        70            1      3            6 Casa 
##  2 Zona … <NA>        3     320       120            1      2            3 Casa 
##  3 Zona … <NA>        3     350       220            2      2            4 Casa 
##  4 Zona … 02          4     400       280            3      5            3 Casa 
##  5 Zona … 01          5     260        90            1      2            3 Apar…
##  6 Zona … 01          5     240        87            1      3            3 Apar…
##  7 Zona … 01          4     220        52            2      2            3 Apar…
##  8 Zona … 01          5     310       137            2      3            4 Apar…
##  9 Zona … 02          5     320       150            2      4            6 Casa 
## 10 Zona … 02          5     780       380            2      3            3 Casa 
## # ℹ 8,309 more rows

Normalización de la variable piso

dfVivienda$piso <- as.numeric(dfVivienda$piso)
dfVivienda
## # A tibble: 8,319 × 9
##    zona    piso estrato preciom areaconst parqueaderos banios habitaciones tipo 
##    <chr>  <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl> <chr>
##  1 Zona …    NA       3     250        70            1      3            6 Casa 
##  2 Zona …    NA       3     320       120            1      2            3 Casa 
##  3 Zona …    NA       3     350       220            2      2            4 Casa 
##  4 Zona …     2       4     400       280            3      5            3 Casa 
##  5 Zona …     1       5     260        90            1      2            3 Apar…
##  6 Zona …     1       5     240        87            1      3            3 Apar…
##  7 Zona …     1       4     220        52            2      2            3 Apar…
##  8 Zona …     1       5     310       137            2      3            4 Apar…
##  9 Zona …     2       5     320       150            2      4            6 Casa 
## 10 Zona …     2       5     780       380            2      3            3 Casa 
## # ℹ 8,309 more rows

Imputación de pisos

Para la variable piso se imputarán los valores faltantes con la media de los valores existentes pero por tipo de vivienda, es decir se imputaran los datos de las casas la media del subset de casas e igualmente para los apartamentos.

# Subconjunto de datos para "Casa"
dfCasa <- subset(dfVivienda, tipo == "Casa")
dfApto <- subset(dfVivienda, tipo == "Apartamento")
mediaPisoCasa <- round(mean(dfCasa$piso, na.rm = TRUE))
mediaPisoApto <- round(mean(dfApto$piso, na.rm = TRUE))
dfVivienda <- dfVivienda %>%
  dplyr::mutate(piso = ifelse(tipo == "Casa" & is.na(piso), mediaPisoCasa, piso)) %>%
  dplyr::mutate(piso = ifelse(tipo == "Apartamento" & is.na(piso), mediaPisoApto, piso))

md.pattern(dfVivienda)

##      zona piso estrato preciom areaconst banios habitaciones tipo parqueaderos
## 6717    1    1       1       1         1      1            1    1            1
## 1602    1    1       1       1         1      1            1    1            0
##         0    0       0       0         0      0            0    0         1602
##          
## 6717    0
## 1602    1
##      1602

Imputación de la variable parqueaderos

Para la variable parqueaderos se imputarán los valores faltantes con la media de los valores existentes pero por estrato, es decir se imputaran los datos de los estratos 2, 3, 4, 5 y 6 con la media de los parqueaderos de cada estrato.

##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

##      zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo
## 8319    1    1       1       1         1            1      1            1    1
##         0    0       0       0         0            0      0            0    0
##       
## 8319 0
##      0

Codificación de variables zona

## Se crea una copia para mantener las variables categóricas
dfViviendaConCategoricas <- dfVivienda 
dfVivienda <- dfVivienda %>%
  mutate(zona = case_when(
    zona == "Zona Centro" ~ 1,
    zona == "Zona Norte" ~ 2,
    zona == "Zona Oeste" ~ 3,
    zona == "Zona Oriente" ~ 4,
    zona == "Zona Sur" ~ 5,
    TRUE ~ NA_real_  # Si existe alguna categoría no especificada, será convertida a NA
  ))
dfVivienda
## # A tibble: 8,319 × 9
##     zona  piso estrato preciom areaconst parqueaderos banios habitaciones tipo  
##    <dbl> <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl> <chr> 
##  1     4     2       3     250        70            1      3            6 Casa  
##  2     4     2       3     320       120            1      2            3 Casa  
##  3     4     2       3     350       220            2      2            4 Casa  
##  4     5     2       4     400       280            3      5            3 Casa  
##  5     2     1       5     260        90            1      2            3 Apart…
##  6     2     1       5     240        87            1      3            3 Apart…
##  7     2     1       4     220        52            2      2            3 Apart…
##  8     2     1       5     310       137            2      3            4 Apart…
##  9     2     2       5     320       150            2      4            6 Casa  
## 10     2     2       5     780       380            2      3            3 Casa  
## # ℹ 8,309 more rows

Codificación de variables tipo

dfVivienda <- dfVivienda %>%
  mutate(tipo = case_when(
    tipo == "Casa" ~ 1,
    tipo == "Apartamento" ~ 2,
    TRUE ~ NA_real_  # Si existe alguna categoría no especificada, será convertida a NA
  ))
dfVivienda
## # A tibble: 8,319 × 9
##     zona  piso estrato preciom areaconst parqueaderos banios habitaciones  tipo
##    <dbl> <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl> <dbl>
##  1     4     2       3     250        70            1      3            6     1
##  2     4     2       3     320       120            1      2            3     1
##  3     4     2       3     350       220            2      2            4     1
##  4     5     2       4     400       280            3      5            3     1
##  5     2     1       5     260        90            1      2            3     2
##  6     2     1       5     240        87            1      3            3     2
##  7     2     1       4     220        52            2      2            3     2
##  8     2     1       5     310       137            2      3            4     2
##  9     2     2       5     320       150            2      4            6     1
## 10     2     2       5     780       380            2      3            3     1
## # ℹ 8,309 more rows

Inspección de datos despues de imputación

summary(dfVivienda)
##       zona            piso           estrato         preciom      
##  Min.   :1.000   Min.   : 1.000   Min.   :3.000   Min.   :  58.0  
##  1st Qu.:3.000   1st Qu.: 2.000   1st Qu.:4.000   1st Qu.: 220.0  
##  Median :5.000   Median : 3.000   Median :5.000   Median : 330.0  
##  Mean   :3.918   Mean   : 3.708   Mean   :4.634   Mean   : 433.9  
##  3rd Qu.:5.000   3rd Qu.: 5.000   3rd Qu.:5.000   3rd Qu.: 540.0  
##  Max.   :5.000   Max.   :12.000   Max.   :6.000   Max.   :1999.0  
##    areaconst       parqueaderos       banios        habitaciones   
##  Min.   :  30.0   Min.   : 1.00   Min.   : 0.000   Min.   : 0.000  
##  1st Qu.:  80.0   1st Qu.: 1.00   1st Qu.: 2.000   1st Qu.: 3.000  
##  Median : 123.0   Median : 1.00   Median : 3.000   Median : 3.000  
##  Mean   : 174.9   Mean   : 1.73   Mean   : 3.111   Mean   : 3.605  
##  3rd Qu.: 229.0   3rd Qu.: 2.00   3rd Qu.: 4.000   3rd Qu.: 4.000  
##  Max.   :1745.0   Max.   :10.00   Max.   :10.000   Max.   :10.000  
##       tipo      
##  Min.   :1.000  
##  1st Qu.:1.000  
##  Median :2.000  
##  Mean   :1.613  
##  3rd Qu.:2.000  
##  Max.   :2.000

Boxplot Zona vs precio

okabe_ito_colors <- c("#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00")
boxplot(dfVivienda$preciom~ dfVivienda$zona, 
        data = dfVivienda, 
        col = okabe_ito_colors,
        ylab = "Precio", xlab = "Zona")

Boxplot Estrato vs precio

boxplot(dfVivienda$preciom~ dfVivienda$estrato, 
        data = dfVivienda, 
        col = okabe_ito_colors,
        ylab = "Precio", xlab = "Estrato")

Boxplot Tipo vs precio

boxplot(dfVivienda$preciom~ dfVivienda$tipo, 
        data = dfVivienda, 
        col = okabe_ito_colors,
        ylab = "Precio", xlab = "Tipo")

Distribución por estratos

estrato_freq <- table(dfVivienda$estrato)
pie(estrato_freq, 
    main = "Distribución de Estrato", 
    col = okabe_ito_colors,, 
    labels = paste(names(estrato_freq), round(100 * estrato_freq / sum(estrato_freq), 1), "%"))

legend("topright", 
       legend = names(estrato_freq), 
       fill = okabe_ito_colors, 
       title = "Estrato")

Conclusiones del análisis exploratorio.

  • Como se esperaba el estrato 6 tiene la media mas alta de precios. Seguid en orden descendiente 5, 4, 3.
  • Las casas tienen un medio mayor a los apartamentos.
  • La zona oeste tiene la media de precios mas alta seguida por la zona sur.
  • Como era de esperarse las zona oriente tiene la media de precios mas bajos.

Analiss de componentes principales (ACP)

Selección de variables numéricas

variablesNumericas <- dfVivienda %>% dplyr::select(piso, preciom, areaconst, parqueaderos, banios, habitaciones)

Escalamiento de las variables

viviendaEscalada <- scale(variablesNumericas)
viviendaEscalada <- as.data.frame(viviendaEscalada)
tail(viviendaEscalada)
##            piso    preciom   areaconst parqueaderos      banios habitaciones
## 8314  0.5564480  1.3268694  0.49008841   -0.6848547  0.62223934   -0.4147626
## 8315 -0.7356317  3.7001064  1.99396219    0.2534368  2.02259346    0.2703863
## 8316 -0.7356317 -0.2248625  0.04941842   -0.6848547 -0.07793773    3.6961306
## 8317 -0.7356317  4.1564981  1.57427649    1.1917284  2.02259346    0.9555352
## 8318  0.5564480  1.7224089  0.09838176    1.1917284  1.32241640    0.2703863
## 8319 -0.7356317  0.2923815 -0.23037205    0.2534368  0.62223934    0.2703863

Componentes principales

res.pca <- prcomp(viviendaEscalada)
res.pca
## Standard deviations (1, .., p=6):
## [1] 1.8045828 1.0608582 0.8605949 0.6093397 0.5622824 0.4358679
## 
## Rotation (n x k) = (6 x 6):
##                     PC1          PC2         PC3         PC4        PC5
## piso          0.1612932 -0.736034230  0.63135600  0.04309734  0.1698949
## preciom      -0.4623411 -0.348312449 -0.17996371  0.28847429 -0.2534730
## areaconst    -0.4807711  0.044908344 -0.02784373  0.62492193  0.4718695
## parqueaderos -0.4183241 -0.341776871 -0.35263812 -0.66424756  0.3521257
## banios       -0.4796202 -0.001632977  0.27597286 -0.11711651 -0.6906018
## habitaciones -0.3522127  0.467013057  0.60639321 -0.26354639  0.2886226
##                     PC6
## piso          0.0539077
## preciom      -0.6964669
## areaconst     0.3909973
## parqueaderos  0.1364644
## banios        0.4507258
## habitaciones -0.3706381
fviz_eig(res.pca, addlabels = TRUE)

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

# Realizar PCA (asumiendo que ya tienes las variables numéricas escaladas)

# Obtener las puntuaciones (scores) en la primera componente principal (PC1)
scores <- res.pca$x

# Seleccionar los índices de los valores más altos y más bajos en PC1 y PC2
extreme_cases <- c(
  which.max(scores[,1]),  # Índice del valor máximo en PC1
  which.min(scores[,1]),  # Índice del valor mínimo en PC1
  which.max(scores[,2]),  # Índice del valor máximo en PC2
  which.min(scores[,2])   # Índice del valor mínimo en PC2
)
casos1 <- rbind(res.pca$x[extreme_cases[1],1:2],res.pca$x[extreme_cases[2],1:2]) # CP1
rownames(casos1) = c(as.character(extreme_cases[1]), as.character(extreme_cases[2]))
casos1 <- as.data.frame(casos1)

casos2 <- rbind(res.pca$x[extreme_cases[3],1:2],res.pca$x[extreme_cases[4],1:2]) # CP2
rownames(casos2) = c(as.character(extreme_cases[3]), as.character(extreme_cases[4]))
casos2 <- as.data.frame(casos2)

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

viviendasExtremas <- dfVivienda[extreme_cases, ]
viviendasExtremas
## # A tibble: 4 × 9
##    zona  piso estrato preciom areaconst parqueaderos banios habitaciones  tipo
##   <dbl> <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl> <dbl>
## 1     5     5       4     160        76            1      0            0     2
## 2     5     2       6    1800      1586           10      4            5     1
## 3     4     1       3     350        72            1      4           10     1
## 4     5     5       5     950       280           10      0            0     2

Conclusiones del análisis de componentes principales

  • Con la primera componente principal (CP1) se explica el 54.3% de la variabilidad de los datos
  • Con CP1 y CP2 se explica el 73.2% de la variabilidad.
  • CP1 esta principalmente influenciada por las variables areaconst, banios y preciom.
  • CP2 esta principalmente influenciada por la variable piso y habitaciones.
  • Al revisar las componentes de CP1 y CP2 podemos observar que tienen una componente inversa al precio.
  • PC1 y PC2 parecen estar fuertemente relacionadas con el precio. Esto podría significar que estas dos componentes principales están capturando la mayor parte de la variabilidad relacionada con factores que influyen en el precio.

Análisis de Conglomerados

variablesForCluster <- dfVivienda %>% dplyr::select(piso, preciom, areaconst, parqueaderos, banios, habitaciones, estrato, tipo, zona)
variablesForCluster
## # A tibble: 8,319 × 9
##     piso preciom areaconst parqueaderos banios habitaciones estrato  tipo  zona
##    <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>   <dbl> <dbl> <dbl>
##  1     2     250        70            1      3            6       3     1     4
##  2     2     320       120            1      2            3       3     1     4
##  3     2     350       220            2      2            4       3     1     4
##  4     2     400       280            3      5            3       4     1     5
##  5     1     260        90            1      2            3       5     2     2
##  6     1     240        87            1      3            3       5     2     2
##  7     1     220        52            2      2            3       4     2     2
##  8     1     310       137            2      3            4       5     2     2
##  9     2     320       150            2      4            6       5     1     2
## 10     2     780       380            2      3            3       5     1     2
## # ℹ 8,309 more rows

Escalamiento de las variables

viviendaEscaladaForCluster <- scale(variablesForCluster)
viviendaEscaladaForCluster <- as.data.frame(viviendaEscaladaForCluster)

Determinar el numero de clusters

Método del codo

wss <- numeric(10)
for (k in 1:10) {
  km_res <- kmeans(viviendaEscaladaForCluster, centers = k, nstart = 25)
  wss[k] <- km_res$tot.withinss
}

# Graficar el método del codo
plot(1:10, wss, type = "b", pch = 19, frame = FALSE,
     xlab = "Número de clusters K",
     ylab = "Suma de las distancias dentro de los clusters",
     main = "Método del Codo")

Se determina que el número de clusters es 5 porque es donde se encuentra el codo aproximadamente.

Clusterización por Clustering Jerárquico (Hierarchical Clustering).

de <- dist(viviendaEscaladaForCluster, method = "manhattan")
hc_emp <- hclust(de, method = "complete" )

cluster_assigments <- cutree(hc_emp, k = 6)
assigned_cluster <- viviendaEscaladaForCluster %>% mutate(cluster = as.factor(cluster_assigments))
table(assigned_cluster$cluster)
## 
##    1    2    3    4    5    6 
## 2199 4178 1630   53  103  156
ggplot(assigned_cluster, aes(x = cluster)) +
  geom_bar(fill = okabe_ito_colors) +  
  labs(title = "Distribución de viviendas en cada clúster",
       x = "Clúster",
       y = "Cantidad de viviendas") +
  theme_minimal() +
  geom_text(stat='count', aes(label=..count..), vjust=-0.5)
## Warning: The dot-dot notation (`..count..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(count)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

library(RColorBrewer)
colors <- brewer.pal(n = 10, name = "Set3") 

ggplot(assigned_cluster, aes(x = preciom, y = areaconst, color = factor(cluster))) +
  geom_point() +
  labs(title = "Relación entre precio y área construida por clúster",
       x = "Precio",
       y = "Área construida",
       color = "Clúster") +
  theme(legend.position = "bottom")

# Dibujar el dendrograma
plot(hc_emp, labels = FALSE, hang = -1, main = "Dendrograma del Clustering Jerárquico")
rect.hclust(hc_emp, k = 6, border = 2:7) # Agrega rectángulos alrededor de los clusters

Resultados de Clustering Jerárquico (Hierarchical Clustering).

AL realizar esta clusterización vemos que no se logra una buena separación de los datos, por lo que se procederá a realizar el clustering con el método de K-means.

Clusterización por K-means

set.seed(123)  # Fijar la semilla para la reproducibilidad
kmeans_result <- kmeans(viviendaEscaladaForCluster, centers = 4, nstart = 25)
assigned_cluster2 <- viviendaEscaladaForCluster %>%
  as.data.frame() %>%
  mutate(cluster = as.factor(kmeans_result$cluster))
table(assigned_cluster2$cluster)
## 
##    1    2    3    4 
## 2250 1738  998 3333
ggplot(assigned_cluster2, aes(x = preciom, y = areaconst, color = cluster)) +
  geom_point(size = 1) +
  labs(title = "Clusters Identificados por K-means",
       x = "Área Construida",
       y = "Precio M2") +
  theme_minimal()

#### Resultados de K-means.

Al realizar agrupar los valores se ven una mejor distribución que con el método jerarquice pero aun se pueden observar algunos valores sobreponiendose.

Clusterización por K-means con PCA

# Realizar el análisis de conglomerados con k-means
num_clusters <- 6
kmeans_result <- kmeans(res.pca$x[, 1:2], centers = num_clusters)

# Agregar la información de los clusters al conjunto de datos original
viviendaEscalada$cluster <- as.factor(kmeans_result$cluster)

# Visualizar los resultados
library(ggplot2)

# Graficar las puntuaciones de los componentes principales coloreadas por cluster
ggplot(viviendaEscalada, aes(x = res.pca$x[, 1], y = res.pca$x[, 2], color = cluster)) +
  geom_point() +
  labs(title = "Resultados del Análisis de Conglomerados")

#### Resultados de K-means con PCA

Aquí podemos observar un agrupamiento más claro de los datos, lo que indica que el método de PCA puede ser el mejor metodo para agrupar los datos, de los 2 previamente implementados.

Análisis de Correspondencia

dfViviendaSoloCategoricas <- dfViviendaConCategoricas %>% dplyr::select(zona, estrato, tipo)
tablaZonaEstrato <- table(dfViviendaSoloCategoricas$zona, dfViviendaSoloCategoricas$estrato)
tablaZonaEstrato
##               
##                   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

Chi-cuadrado para Zona vs Estrato

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

El resultado indica que se rechaza la hipótesis de independencia de las variables Zona~estrato (p-value: 0.0000), indicando grado tipo de relación entre ellas.

resultados_ac <- CA(tablaZonaEstrato)

valores_prop <-resultados_ac$eig
valores_prop
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.32215213              69.965515                          69.96551
## dim 2 0.12745096              27.680002                          97.64552
## dim 3 0.01084108               2.354483                         100.00000
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")

#### Resultados de Análisis de Correspondencia zona vs estrato

Es practicante los mismos resultados obtenidos en el ejemplo del material entregado Experiencia, Análisis de correspondencia: - 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 - La primera componente resumen el 70% datos y la segunda el 27.7% restante, acumulando 97.7%. — ### Análisis de Correspondencia con variables categóricas combinadas Zona_tipo vs Estrato

datos_inmobiliarios <- dfViviendaConCategoricas %>%
  mutate(zona_tipo = paste(zona, tipo, sep = "-"))
datos_inmobiliarios
## # A tibble: 8,319 × 10
##    zona    piso estrato preciom areaconst parqueaderos banios habitaciones tipo 
##    <chr>  <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl> <chr>
##  1 Zona …     2       3     250        70            1      3            6 Casa 
##  2 Zona …     2       3     320       120            1      2            3 Casa 
##  3 Zona …     2       3     350       220            2      2            4 Casa 
##  4 Zona …     2       4     400       280            3      5            3 Casa 
##  5 Zona …     1       5     260        90            1      2            3 Apar…
##  6 Zona …     1       5     240        87            1      3            3 Apar…
##  7 Zona …     1       4     220        52            2      2            3 Apar…
##  8 Zona …     1       5     310       137            2      3            4 Apar…
##  9 Zona …     2       5     320       150            2      4            6 Casa 
## 10 Zona …     2       5     780       380            2      3            3 Casa 
## # ℹ 8,309 more rows
## # ℹ 1 more variable: zona_tipo <chr>
tablaZonaEstrato2 <- table(datos_inmobiliarios$zona_tipo, datos_inmobiliarios$estrato)
tablaZonaEstrato2
##                           
##                               3    4    5    6
##   Zona Centro-Apartamento    14    7    3    0
##   Zona Centro-Casa           91    7    1    1
##   Zona Norte-Apartamento    337  246  498  117
##   Zona Norte-Casa           235  161  271   55
##   Zona Oeste-Apartamento     29   58  231  711
##   Zona Oeste-Casa            25   26   59   59
##   Zona Oriente-Apartamento   58    2    1    1
##   Zona Oriente-Casa         282    6    1    0
##   Zona Sur-Apartamento      201 1091 1033  462
##   Zona Sur-Casa             181  525  652  581
resultados_ac <- CA(tablaZonaEstrato2)

summary(resultados_ac)
## 
## Call:
## CA(X = tablaZonaEstrato2) 
## 
## The chi square of independence between the two variables is equal to 4109.091 (p-value =  0 ).
## 
## Eigenvalues
##                        Dim.1   Dim.2   Dim.3
## Variance               0.329   0.153   0.012
## % of var.             66.652  30.903   2.444
## Cumulative % of var.  66.652  97.556 100.000
## 
## Rows
##                            Iner*1000     Dim.1     ctr    cos2     Dim.2
## Zona Centro-Apartamento  |     3.831 |   1.112   1.083   0.931 |  -0.009
## Zona Centro-Casa         |    45.211 |   1.854  12.545   0.914 |   0.526
## Zona Norte-Apartamento   |    25.991 |   0.351   5.395   0.683 |  -0.130
## Zona Norte-Casa          |    21.813 |   0.468   5.769   0.871 |  -0.129
## Zona Oeste-Apartamento   |   144.507 |  -0.672  16.970   0.387 |   0.847
## Zona Oeste-Casa          |     1.965 |  -0.142   0.125   0.209 |   0.246
## Zona Oriente-Apartamento |    29.934 |   1.908   8.240   0.906 |   0.589
## Zona Oriente-Casa        |   154.700 |   2.012  42.725   0.909 |   0.612
## Zona Sur-Apartamento     |    53.336 |  -0.181   3.347   0.207 |  -0.345
## Zona Sur-Casa            |    12.653 |  -0.232   3.802   0.989 |   0.017
##                              ctr    cos2     Dim.3     ctr    cos2  
## Zona Centro-Apartamento    0.000   0.000 |   0.303   2.198   0.069 |
## Zona Centro-Casa           2.177   0.074 |   0.221   4.860   0.013 |
## Zona Norte-Apartamento     1.587   0.093 |  -0.201  48.091   0.223 |
## Zona Norte-Casa            0.951   0.067 |  -0.126  11.336   0.063 |
## Zona Oeste-Apartamento    58.066   0.613 |  -0.006   0.040   0.000 |
## Zona Oeste-Casa            0.807   0.627 |  -0.126   2.676   0.164 |
## Zona Oriente-Apartamento   1.696   0.086 |   0.170   1.791   0.007 |
## Zona Oriente-Casa          8.515   0.084 |   0.173   8.648   0.007 |
## Zona Sur-Apartamento      26.159   0.749 |   0.084  19.779   0.045 |
## Zona Sur-Casa              0.043   0.005 |   0.017   0.580   0.006 |
## 
## Columns
##                            Iner*1000     Dim.1     ctr    cos2     Dim.2
## 3                        |   257.273 |   1.186  74.686   0.956 |   0.255
## 4                        |    56.732 |  -0.134   1.398   0.081 |  -0.429
## 5                        |    27.145 |  -0.121   1.476   0.179 |  -0.217
## 6                        |   152.790 |  -0.556  22.440   0.484 |   0.574
##                              ctr    cos2     Dim.3     ctr    cos2  
## 3                          7.429   0.044 |   0.017   0.419   0.000 |
## 4                         30.813   0.829 |   0.141  42.197   0.090 |
## 5                         10.232   0.575 |  -0.142  55.236   0.246 |
## 6                         51.527   0.515 |   0.033   2.148   0.002 |
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")

Resultados de Análisis de Correspondencia zona_tipo vs estrato

  • El valor del chi cuadrado es 4109.091 con un p-valor de 0 indica que hay una fuerte asociación entre las variables (zonas_tipo vs estratos) y que esta asociación no es producto del azar. Un p-valor de 0 sugiere que la independencia entre las variables se rechaza la hipótesis nula.
  • Dim.1 (66.652% de varianza explicada): Esta dimensión explica el 66.65% de la variabilidad en los datos, lo que la convierte en la dimensión más significativa. Refleja la mayor parte de la asociación entre las variables.
  • Dim.2 (30.903% de varianza explicada): Explica el 30.90% de la variabilidad adicional, capturando asociaciones que no son visibles en la primera dimensión.
  • Dim.3 (2.444% de varianza explicada): Explica el 2.44% de la variabilidad, lo que sugiere que esta dimensión tiene un impacto menor en la estructura de los datos.
  • Cumulative % of var.: Juntas, las tres dimensiones explican el 100% de la variabilidad en los datos, lo cual es esperado ya que se han considerado todas las dimensiones posibles.
  • Zona Oriente-Casa:
    • Inercia (Iner*1000): 154.700, lo que indica una alta contribución a la variabilidad total en los datos.
    • Dim.1 (Coord = 2.012, ctr = 42.725, cos2 = 0.909): La coordenada 2.012 en la Dim.1 sugiere que esta combinación está fuertemente asociada con las características representadas en la primera dimensión. Su contribución (ctr) del 42.725% y un cos2 de 0.909 indican que está bien representada en esta dimensión.
    • Dim.2 (Coord = 0.612, ctr = 8.515, cos2 = 0.084): Menos significativa que la primera dimensión, pero aún contribuye a la estructura del análisis.
    • Dim.3 (Coord = 0.173, ctr = 8.648, cos2 = 0.007): Esta dimensión tiene una influencia mínima en la interpretación de la categoría.
  • Zona Centro-Casa y Zona Oriente-Casa son las categorías con mayor contribución a la primera dimensión, sugiriendo que están muy alineadas con las principales asociaciones capturadas en la Dim.1.
  • Zona Oeste-Apartamento contribuye significativamente a la Dim.2, lo que indica una relación distinta que es capturada mejor en esta segunda dimensión.