1 Categorización de variables

Con el objetivo de realizar un Análisis de Correspondencias Múltiples, y en coherencia con las temáticas abordadas durante el tercer corte, se llevará a cabo una discretización por cuantiles. Este método permite transformar las variables numéricas en categorías ordenadas dividiendo su distribución en partes iguales, garantizando así una partición equilibrada de los datos y facilitando la interpretación de los patrones presentes en las distintas dimensiones del plano factorial.

num_vars <- BostonHousing[, sapply(BostonHousing, is.numeric)]

# Función robusta que devuelve factores con etiquetas fijas
discretize_3 <- function(x){
  # preserva NAs
  nas <- is.na(x)
  x_no_na <- x[!nas]

  # Si todo NA
  if(length(x_no_na) == 0){
    return(factor(rep(NA, length(x)), levels = c("Bajo","Medio","Alto")))
  }

  uniq <- unique(x_no_na)

  # Si solo 1 valor único
  if(length(uniq) == 1){
    out <- rep(NA, length(x))
    out[!nas] <- "Unico"
    return(factor(out, levels = c("Unico", "Bajo","Medio","Alto")))
  }

  # Si 2 valores únicos -> 2 grupos
  if(length(uniq) == 2){
    groups2 <- rep(NA_integer_, length(x))
    groups2[!nas] <- ntile(x_no_na, 2)            # 1 o 2
    labels2 <- c("Bajo","Alto")
    out <- rep(NA, length(x))
    out[!nas] <- labels2[groups2]
    return(factor(out, levels = labels2))
  }

  # Caso general: 3 grupos con ntile
  groups3 <- rep(NA_integer_, length(x))
  groups3[!nas] <- ntile(x_no_na, 3)             # 1,2 o 3
  labels3 <- c("Bajo","Medio","Alto")
  out <- rep(NA, length(x))
  out[!nas] <- labels3[groups3]
  factor(out, levels = labels3)
}

# Aplicar a todas las numéricas y crear df
df <- as.data.frame(lapply(num_vars, discretize_3))

# Comprobaciones rápidas
str(df)               # confirma que son factores
## 'data.frame':    506 obs. of  13 variables:
##  $ crim   : Factor w/ 3 levels "Bajo","Medio",..: 1 1 1 1 1 1 1 2 2 2 ...
##  $ zn     : Factor w/ 3 levels "Bajo","Medio",..: 3 1 1 1 1 1 3 3 3 3 ...
##  $ indus  : Factor w/ 3 levels "Bajo","Medio",..: 1 2 2 1 1 1 2 2 2 2 ...
##  $ nox    : Factor w/ 3 levels "Bajo","Medio",..: 2 1 1 1 1 1 2 2 2 2 ...
##  $ rm     : Factor w/ 3 levels "Bajo","Medio",..: 3 2 3 3 3 2 2 2 1 2 ...
##  $ age    : Factor w/ 3 levels "Bajo","Medio",..: 2 2 2 1 1 2 2 3 3 2 ...
##  $ dis    : Factor w/ 3 levels "Bajo","Medio",..: 2 3 3 3 3 3 3 3 3 3 ...
##  $ rad    : Factor w/ 3 levels "Bajo","Medio",..: 1 1 1 1 1 1 2 2 2 2 ...
##  $ tax    : Factor w/ 3 levels "Bajo","Medio",..: 1 1 1 1 1 1 2 2 2 2 ...
##  $ ptratio: Factor w/ 3 levels "Bajo","Medio",..: 1 1 1 2 2 2 1 1 1 1 ...
##  $ b      : Factor w/ 3 levels "Bajo","Medio",..: 3 3 2 2 3 2 3 3 2 2 ...
##  $ lstat  : Factor w/ 3 levels "Bajo","Medio",..: 1 2 1 1 1 1 2 3 3 3 ...
##  $ medv   : Factor w/ 3 levels "Bajo","Medio",..: 3 2 3 3 3 3 2 3 1 2 ...
lapply(df, function(z) table(z, useNA = "ifany"))  # tablas por variable
## $crim
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $zn
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $indus
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $nox
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $rm
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $age
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $dis
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $rad
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $tax
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $ptratio
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $b
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $lstat
## z
##  Bajo Medio  Alto 
##   169   169   168 
## 
## $medv
## z
##  Bajo Medio  Alto 
##   169   169   168
head(df)
##   crim   zn indus   nox    rm   age   dis  rad  tax ptratio     b lstat  medv
## 1 Bajo Alto  Bajo Medio  Alto Medio Medio Bajo Bajo    Bajo  Alto  Bajo  Alto
## 2 Bajo Bajo Medio  Bajo Medio Medio  Alto Bajo Bajo    Bajo  Alto Medio Medio
## 3 Bajo Bajo Medio  Bajo  Alto Medio  Alto Bajo Bajo    Bajo Medio  Bajo  Alto
## 4 Bajo Bajo  Bajo  Bajo  Alto  Bajo  Alto Bajo Bajo   Medio Medio  Bajo  Alto
## 5 Bajo Bajo  Bajo  Bajo  Alto  Bajo  Alto Bajo Bajo   Medio  Alto  Bajo  Alto
## 6 Bajo Bajo  Bajo  Bajo Medio Medio  Alto Bajo Bajo   Medio Medio  Bajo  Alto

2 Descripción de dimensiones

2.1 Primera Dimensión

Considerando los valores de eta cuadrado, los cuales representan la proporción de inercia explicada por cada variable, se observa que la primera dimensión está definida principalmente por las variables crim, indus, nox, tax,l o cual indica una relación de la primera correspondecia con factores urbanos e industriales.

kable(res.mca$var$eta2[, "Dim 1", drop = FALSE], caption = "Eta² - Dimensión 1")
Eta² - Dimensión 1
Dim 1
crim 0.7785466
zn 0.4091554
indus 0.7693224
nox 0.7560097
rm 0.1505107
age 0.5963996
dis 0.6498886
rad 0.4241035
tax 0.6798048
ptratio 0.5173128
b 0.1993974
lstat 0.5967976
medv 0.5396137

Teniendo en cuenta lo anterior y los valores de v.test, se evidencia que, mientras las categorías crímen bajo y medio se encuentran hacia el lado izquiero del plano factorial, la categoría crímen alto se ubica hacia el lado derecho. Asimismo, se observa que la variable indus presenta una oposición marcada entre sus modalidades: aquellos sectores con un indice bajo y medio de industrias se asocian fuertemente con los valores negativos de la dimensión, mientras que aquellos sectores con un indice alto se relacionan con los valores negativos. De forma similar, las categorías relacionadas con el nivel de contaminación muestran que las zonas con baja y media contaminación se asocian negativamente con la primera dimensión, a diferencia del nivel alto, que presenta una asociación positiva. En cuanto a los impuestos, los valores del v.test muestran una oposición marcada entre las categorías. Los sectores con impuestos bajos y medios v.test negativo en la primera dimensión. Por el contrario, impuestos altos exhiben un v.test positivo de gran magnitud, ubicándose claramente en el lado positivo de la dimensión.

kable(res.mca$var$v.test[, "Dim 1", drop = FALSE], caption = "v.test - Dimensión 1")
v.test - Dimensión 1
Dim 1
crim_Bajo -15.1726278
crim_Medio -3.4354449
crim_Alto 18.6357428
zn_Bajo -1.4291123
zn_Medio 13.0913218
zn_Alto -11.6795511
indus_Bajo -15.2373153
indus_Medio -3.1761627
indus_Alto 18.4408586
nox_Bajo -16.3060881
nox_Medio -1.1367356
nox_Alto 17.4687610
rm_Bajo 7.0469741
rm_Medio 0.9069934
rm_Alto -7.9657950
age_Bajo -14.8350130
age_Medio -0.3519931
age_Alto 15.2095891
dis_Bajo 16.6777462
dis_Medio -2.2431160
dis_Alto -14.4560943
rad_Bajo -9.2128414
rad_Medio -5.2175797
rad_Alto 14.4518791
tax_Bajo -13.2242025
tax_Medio -4.5961967
tax_Alto 17.8468979
ptratio_Bajo -8.6488663
ptratio_Medio -7.4759909
ptratio_Alto 16.1488347
b_Bajo 9.8585232
b_Medio -6.5636714
b_Alto -3.2997513
lstat_Bajo -13.4135444
lstat_Medio -2.8082221
lstat_Alto 16.2458881
medv_Bajo 15.9222999
medv_Medio -4.2150565
medv_Alto -11.7246520

3 Segunda dimensión

Considerando los valores de eta cuadrado, los cuales representan la proporción de inercia explicada por cada variable, se observa que la segunda dimensión está definida principalmente por las variables Nox, indus y dis, lo cual indica una relación de la segunda correspondecia con aspectos industriales.

kable(res.mca$var$eta2[, "Dim 2", drop = FALSE], caption = "Eta² - Dimensión 2")
Eta² - Dimensión 2
Dim 2
crim 0.3271260
zn 0.2713467
indus 0.4510363
nox 0.5278058
rm 0.2329337
age 0.1859021
dis 0.2974626
rad 0.0817332
tax 0.0829252
ptratio 0.0524721
b 0.0092732
lstat 0.2787190
medv 0.2410165

Teniendo en cuenta lo anterior y los valores de v.test, se evidencia que, mientras las categorías crímen bajo y medio se encuentran hacia el lado izquiero del plano factorial, la categoría crímen alto se ubica hacia el lado derecho. Asimismo, se observa que la variable indus presenta una oposición marcada entre sus modalidades: aquellos sectores con un indice bajo y alto de industrias se asocian fuertemente con los valores positivos de la dimensión, mientras que aquellos sectores con un indice medio se relacionan con los valores negativos. De forma similar, las categorías relacionadas con la cercania a centros de trabajo muestran que las zonas cercanas se asocian positivamente con la primera dimensión, a diferencia de los que se encuentran a una distancia media o lejana, que presenta una asociación negativa.

kable(res.mca$var$v.test[, "Dim 2" , drop = FALSE], caption = "v.test - Dimensión 2")
v.test - Dimensión 2
Dim 2
crim_Bajo 7.2896718
crim_Medio -12.8141442
crim_Alto 5.5326872
zn_Bajo -11.0453354
zn_Medio 2.1848577
zn_Alto 8.8736532
indus_Bajo 9.4920948
indus_Medio -14.9115115
indus_Alto 5.4274753
nox_Bajo 9.3174135
nox_Medio -16.2711836
nox_Alto 6.9641103
rm_Bajo -5.8214914
rm_Medio -4.9978058
rm_Alto 10.8353853
age_Bajo 6.1823330
age_Medio -9.5549347
age_Alto 3.3776167
dis_Bajo 6.0078903
dis_Medio -12.2553338
dis_Alto 6.2567335
rad_Bajo -1.4173182
rad_Medio -4.7106311
rad_Alto 6.1370616
tax_Bajo 1.1923687
tax_Medio -6.1008148
tax_Alto 4.9157448
ptratio_Bajo 4.1472574
ptratio_Medio -4.7179993
ptratio_Alto 0.5715905
b_Bajo 2.1291627
b_Medio -0.7330603
b_Alto -1.3981785
lstat_Bajo 9.7304832
lstat_Medio -10.7520392
lstat_Alto 1.0230751
medv_Bajo 2.1548597
medv_Medio -10.4416356
medv_Alto 8.2990983

4 Análisis e interpretación de gráficas del MCA

4.1 Nube de puntos de categorías y nube de individuos

4.1.1 Dimensiones 1 y 2

En el primer cuadrante del plano se observa un conjunto de categorías que tienden a asociarse entre sí y que, en conjunto, representan patrones relacionados a sectores urbanos industrializados.Este grupo incluye categorías altas de criminalidad, contaminación atmosférica, proporción de uso industrial del suelo, carga tributaria y accesibilidad radial, junto con valores bajos en la distancia a los centros de empleo

Por otro lado, en el segundo cuadrante se evidencia un conjunto de categorías asociadas principalmente a zonas residenciales de mayor calidad. En este espacio se ubican categorías bajas de criminalidad, contaminación e industralización, junto con valores altos en el número de habitaciones por vivienda, el valor mediano de la propiedad y la proporción de zonas residenciales.

En cuanto al tercer cuadrante, se agrupa un conjunto de categorías que configuran un perfil que reflejan condiciones intemedias.Aquí predominan valores medios en variables como criminalidad, distancia a los centros de empleo, proporción de población de bajo estatus, número de habitaciones y valor de la vivienda. Por último, en el cuarto cuadrante no se identifican categorías relacionadas.

fviz_mca_var(res.mca, col.var = "purple", shape.var = 10, repel = TRUE,
             ggtheme = theme_grey())+labs(title = "                     Nube de puntos de Categorias")

Para complementar la interpretación de la nube de individuos, se implementó un procedimiento de clasificación basado en un clustering jerárquico ascendente (HCA), que permite agrupar a los individuos considerando ciertas similitudes. Específicamente, se empleó el método de Ward. El número de clústeres se definió a partir de la visualización del dendrograma generado mediante este método. Considerando lo anterior, se observó la existencia de tres grupos principales.

El clúster número uno (color negro) se caracteriza principalmente por agrupar sectores pertenecientes a zonas residenciales, donde se observan índices bajos de criminalidad, contaminación e industrialización, junto con valores medianos de vivienda relativamente altos. En conjunto, este clúster representa áreas de buena calidad habitacional y condiciones ambientales favorables.

Por otro lado, el clúster número dos (color rojo) está conformado principalmente por sectores pertenecientes al estrato medio, los cuales presentan características intermedias en términos de criminalidad, contaminación, valor de la vivienda y nivel de industrialización.

Por último, el clúster número tres (color verde) está constituido principalmente por sectores que presentan condiciones urbanas desfavorables, caracterizadas por valores altos de criminalidad, contaminación atmosférica e industralización. Además, estos sectores tienden a estár cerca de los centros de empleo y muestran valores relativamente bajos en el precio mediano de la vivienda.

fviz_mca_ind(res.mca)

# ---------------------------------------------------
# 1. Extraer coordenadas de individuos del ACM (Dim 1 y Dim 2)
# ---------------------------------------------------
coords_ind <- res.mca$ind$coord[, 1:2]  # Solo las dos primeras dimensiones

# ---------------------------------------------------
# 2. Matriz de distancias y clustering con Ward
# ---------------------------------------------------
d_ind <- dist(coords_ind)
hc_ind <- hclust(d_ind, method = "ward.D2")

# ---------------------------------------------------
# 3. Cortar el dendrograma en k clusters
# ---------------------------------------------------
clusters_ind <- cutree(hc_ind, k = 3)

# ---------------------------------------------------
# 4. Crear gráfico usando plot() (sin ggplot)
# ---------------------------------------------------
plot(
  coords_ind,
  col = clusters_ind,
  pch = 19,
  xlab = "Dim 1",
  ylab = "Dim 2",
  main = "Clusters de individuos ACM"
)

# Opcional: añadir etiquetas de individuos
# text(coords_ind, labels = rownames(coords_ind), pos = 3, cex = 0.7)

# ---------------------------------------------------
# 5. Añadir una leyenda
# ---------------------------------------------------
legend(
  "topright",
  legend = paste("Cluster", 1:3),
  col = 1:3,
  pch = 19
)