Introducción a multivariados: práctica

Author

Valentina Cardona & Aura Nidia Herrera

Introducción

Existen métodos según el tipo de datos. El Análisis de Componentes Principales (ACP) se aplica a tablas que cruzan individuos con variables numéricas y el Análisis de Correspondencias Múltiples (ACM), a variables cualitativas codificadas (Escofier 1992).

Ambos buscan reducir la dimensionalidad, resumiendo la información original en unos pocos ejes (Pardo 2020).

Este cuaderno incluye un ejercicio práctico para cada análisis, con el fin de ilustrar sus fundamentos teóricos.

Librerías

En primer lugar, es necesario cargar los paquetes que se utilizarán a lo largo del cuaderno.

Code
# Lista de paquetes que se necesitan
paquetes <- c("haven", # Importación datos
              "tidyverse", # Manejo de datos
              "explor", "FactoMineR", "factoextra", # Análisis
              "plotly", "wesanderson", # Gráficos y paleta
              "here") # Directorio

# Utilizar lapply para cargar cada paquete si aún no está instalado
lapply(paquetes, FUN = function(x){
  if (!require(x, character.only = TRUE)) {
    install.packages(x, dependencies = TRUE)
    library(x, character.only = TRUE)}}
)

# Establecer directorio
setwd(here())

Análisis de Componentes Principales (ACP)

Para el presente análisis, se utiliza un conjunto de datos que reúne los principales indicadores de los niveles preescolar, básica y media, desagregados por departamento entre los años 2011 y 2023 (para el ejercicio solo se tomarán hasta 2017). Esta información fue publicada por el MEN (2024) y se encuentra disponible en el portal de Datos Abiertos.

La tabla original contiene 230 filas, correspondientes a los departamentos repetidos por cada año, y 37 indicadores educativos. De estos, solo 4 son variables categóricas; los demás corresponden a tasas y porcentajes.

Code
# Cargar datos
educ <- read.csv("MEN_ESTADISTICAS_EN_EDUCACION 2011_2017.csv")

str(educ)
'data.frame':   230 obs. of  37 variables:
 $ AÑO                        : int  2011 2011 2011 2011 2011 2011 2011 2011 2011 2011 ...
 $ CÓDIGO_DEPARTAMENTO        : int  5 8 11 13 15 17 18 19 20 23 ...
 $ DEPARTAMENTO               : chr  "Antioquia" "Atlántico" "Bogotá, D.C." "Bolívar" ...
 $ POBLACIÓN_5_16             : int  1288473 523935 1479334 496676 300501 201185 124148 328682 263789 405431 ...
 $ TASA_MATRICULACIÓN_5_16    : num  94 99.3 90.7 91.6 86.2 ...
 $ COBERTURA_NETA             : num  93.8 99 90.3 91.4 86.1 ...
 $ COBERTURA_NETA_TRANSICIÓN  : num  70.3 50.6 68.6 59.7 63.4 ...
 $ COBERTURA_NETA_PRIMARIA    : num  94.1 98.9 87 90.8 82.5 ...
 $ COBERTURA_NETA_SECUNDARIA  : num  75.7 80.2 84.7 67.3 74.7 ...
 $ COBERTURA_NETA_MEDIA       : num  44.4 50.2 55 39.2 49.1 ...
 $ COBERTURA_BRUTA            : num  106.8 107.9 97.8 110.4 104.2 ...
 $ COBERTURA_BRUTA_TRANSICIÓN : num  85.7 84.2 82 98.8 78.9 ...
 $ COBERTURA_BRUTA_PRIMARIA   : num  117.5 120.4 97.9 126.5 99.9 ...
 $ COBERTURA_BRUTA_SECUNDARIA : num  111 108 106 108 120 ...
 $ COBERTURA_BRUTA_MEDIA      : num  84.1 88 87.8 80.6 94.8 ...
 $ TAMAÑO_PROMEDIO_DE_GRUPO   : num  27.5 24.4 26.8 20.8 22.8 ...
 $ SEDES_CONECTADAS_A_INTERNET: chr  "Alta" "Muy Alta" "Muy Alta" "Media" ...
 $ DESERCIÓN                  : num  3.97 2.76 3.95 3.14 3.07 4.13 3.64 2.75 7.07 4.59 ...
 $ DESERCIÓN_TRANSICIÓN       : num  3.62 2.6 10.05 1.85 2.4 ...
 $ DESERCIÓN_PRIMARIA         : num  3.65 3.06 5.3 2.93 2.24 3.92 3.56 1.96 7.36 4.08 ...
 $ DESERCIÓN_SECUNDARIA       : num  4.57 2.42 1.96 3.79 4.03 4.87 3.91 3.91 7.62 5.3 ...
 $ DESERCIÓN_MEDIA            : num  3.71 2.61 2.55 3.13 3.51 2.82 3.39 3.6 5.42 4.1 ...
 $ APROBACIÓN                 : num  94 96.7 96 94.8 94.2 ...
 $ APROBACIÓN_TRANSICIÓN      : num  0.07 0.12 0 0.46 0.17 0.3 0.05 1.17 0.46 0.22 ...
 $ APROBACIÓN_PRIMARIA        : num  94.6 96.5 94.7 95.5 96.1 ...
 $ APROBACIÓN_SECUNDARIA      : num  92.9 96.9 98 93.5 91.7 ...
 $ APROBACIÓN_MEDIA           : num  93.3 96.6 97.5 93.2 93.2 ...
 $ REPROBACIÓN                : num  2.06 0.54 0 2.1 2.73 5.25 0.3 4.72 2.39 1.12 ...
 $ REPROBACIÓN_TRANSICIÓN     : num  0.07 0.12 0 0.46 0.17 0.3 0.05 1.17 0.46 0.22 ...
 $ REPROBACIÓN_PRIMARIA       : num  94.6 96.5 94.7 95.5 96.1 ...
 $ REPROBACIÓN_SECUNDARIA     : num  2.54 0.67 0 2.75 4.31 7.25 0.08 4.64 3.74 1.37 ...
 $ REPROBACIÓN_MEDIA          : num  2.96 0.75 0 3.67 3.26 5.15 3.15 4.63 3.78 2.71 ...
 $ REPITENCIA                 : num  4.25 1.82 3.23 4.43 2.62 4.67 4.17 2.09 1.67 4.07 ...
 $ REPITENCIA_TRANSICIÓN      : num  0.07 0.12 0 0.46 0.17 0.3 0.05 1.17 0.46 0.22 ...
 $ REPITENCIA_PRIMARIA        : num  4.56 1.77 2.3 4.44 1.9 4.15 3.7 1.75 1.57 4.18 ...
 $ REPITENCIA_SECUNDARIA      : num  5.27 2.18 5.11 5.37 4.19 6.55 5.8 3.13 2.19 4.53 ...
 $ REPITENCIA_MEDIA           : num  1.68 0.88 2.57 2.28 1.55 3.07 2.87 1.57 0.97 2.43 ...

Para este ejercicio, se plantea el siguiente objetivo:

Explorar relaciones entre los principales indicadores en la educación secundaria y media durante el periodo 2011-2017

Dada la gran cantidad de variables disponibles, se extrajeron aquellas que se consideran más relevantes para el ejercicio.

Variable Descripción
SEDES_CONECTADAS_A_INTERNET\(^*\) Porcentaje de sedes oficiales de una Entidad Territorial Certificada (ETC) que se encuentran conectadas a una red de Internet.
COBERTURA_NETA Relación entre el número de estudiantes matriculados que tienen la edad teórica y el total de la población correspondiente a esa misma edad.
APROBACIÓN Tasa de aprobación de estudiantes del sector oficial. Identifica el porcentaje de alumnos que aprueba de acuerdo con los planes y programas de estudio vigentes.
REPITENCIA Tasa de repitencia del sector oficial. Corresponde al porcentaje de alumnos matriculados en un año escolar que se encuentran repitiendo el mismo grado cursado el año anterior.
DESERCIÓN Tasa de deserción intra - anual del sector oficial. Identifica la proporción de alumnos matriculados que por factores culturales, coyunturales o de prestación del servicio educativo, abandonan sus estudios durante el año lectivo.

Para el ejercicio, se seleccionaron únicamente las variables correspondientes a básica secundaria (6° a 9°) y educación media (10° y 11°).

Code
# Seleccionar variables para análisis
educ <- educ %>% 
  mutate(row_id = paste0(DEPARTAMENTO, "_", AÑO)) %>%
  column_to_rownames("row_id") %>% 
  select(SEDES_CONECTADAS_A_INTERNET,
         matches("^COBERTURA_NETA_|^APROBACIÓN_|^REPITENCIA_|^DESERCIÓN_"),
         -matches("TRANSICIÓN|PRIMARIA"))

# Convertir a factor la variable cualitativa
sedes <- factor(educ$SEDES_CONECTADAS_A_INTERNET,
                levels = c("Muy Alta", "Alta", "Media", "Baja", "Muy Baja"))
  
str(educ)
'data.frame':   230 obs. of  9 variables:
 $ SEDES_CONECTADAS_A_INTERNET: chr  "Alta" "Muy Alta" "Muy Alta" "Media" ...
 $ COBERTURA_NETA_SECUNDARIA  : num  75.7 80.2 84.7 67.3 74.7 ...
 $ COBERTURA_NETA_MEDIA       : num  44.4 50.2 55 39.2 49.1 ...
 $ DESERCIÓN_SECUNDARIA       : num  4.57 2.42 1.96 3.79 4.03 4.87 3.91 3.91 7.62 5.3 ...
 $ DESERCIÓN_MEDIA            : num  3.71 2.61 2.55 3.13 3.51 2.82 3.39 3.6 5.42 4.1 ...
 $ APROBACIÓN_SECUNDARIA      : num  92.9 96.9 98 93.5 91.7 ...
 $ APROBACIÓN_MEDIA           : num  93.3 96.6 97.5 93.2 93.2 ...
 $ REPITENCIA_SECUNDARIA      : num  5.27 2.18 5.11 5.37 4.19 6.55 5.8 3.13 2.19 4.53 ...
 $ REPITENCIA_MEDIA           : num  1.68 0.88 2.57 2.28 1.55 3.07 2.87 1.57 0.97 2.43 ...

A partir de estas variables se construye la matriz de datos para el modelo de reducción de dimensiones. En el ACP, es común centrar previamente la tabla restando la media a cada valor (Escofier 1992); este paso puede indicarse directamente en la función utilizada. Si las variables se encuentran en la misma escala, no es necesario centrarlas.

Adicionalmente, para evitar que los resultados sean sensibles a las unidades de medida, también se estandarizan las variables, ajustando su varianza a 1. Así, todas tienen la misma variabilidad e influencia.

A continuación, se presenta un primer resumen de las componentes principales.

Code
# Extrayendo componentes
acp <- prcomp(educ[-1], center = TRUE, scale = TRUE)

# Resumen de las componentes
summary(acp)

# Valores propios
(acp$sdev)^2
Importance of components:
                          PC1    PC2    PC3     PC4     PC5     PC6     PC7
Standard deviation     2.0075 1.4099 1.1231 0.65822 0.37428 0.29019 0.19684
Proportion of Variance 0.5038 0.2485 0.1577 0.05416 0.01751 0.01053 0.00484
Cumulative Proportion  0.5038 0.7522 0.9099 0.96405 0.98156 0.99209 0.99693
                           PC8
Standard deviation     0.15664
Proportion of Variance 0.00307
Cumulative Proportion  1.00000
[1] 4.03008048 1.98776095 1.26132331 0.43325581 0.14008319 0.08421201 0.03874683
[8] 0.02453743

La primera componente principal (PC1) explica el 50,3% de la varianza, la segunda (PC2) el 24,8%, y la tercera (PC3) el 15,7% lo que suma un 91,0% de la variabilidad total.

Por otro lado, la función explor() despliega una interfaz gráfica interactiva y es posible observar lo siguiente:

  • El Porcentaje de inercia (varianza) extraído por un factor que refleja la importancia relativa de cada factor y debe interpretarse según el número de variables consideradas (Escofier 1992).
  • Un plano factorial de las variables estandarizadas o círculo de correlaciones muestra flechas que parten del origen y tienen longitud uno.
  • La coordenada de una variable sobre un eje representa su correlación con ese componente (Escofier 1992).
Code
# Gráfico interactivo
explor(acp)

Shiny applications not supported in static R Markdown documents

Como apreciación general, se puede destacar:

  • El eje 1 puede representar la oposición de la deserción secundaria y media y la aprobación secundaria y media.

  • Los ejes 2 y 3 correlacionan con las variables de repitencia y cobertura neta respectivamente.

  • Vaupés y Guainía destacan en el eje 1, sugiriendo mayores tasas de deserción.

  • Entre 2013 y 2015, Bogotá presenta los valores más altos en el eje 2, indicando mayor repitencia relativa.

Gráfico 3D de variables

Un gráfico 3D permite observar cómo las tres principales componentes interactúan con las variables.

Code
# Extrae los componentes principales
components <- acp[["rotation"]]
components <- data.frame(components)
components$var <- rownames(components)  # Agregar nombres de variables

# Gráfico 3D interactivo usando los primeros tres componentes principales
fig <- plot_ly()

# Añadir flechas
for (i in 1:nrow(components)) {
  fig <- fig %>%
    add_trace(
      type = "scatter3d",
      mode = "lines+markers",
      x = c(0, components$PC1[i]),
      y = c(0, components$PC2[i]),
      z = c(0, components$PC3[i]),
      line = list(width = 4),
      marker = list(size = 6),
      name = components$var[i],
      text = components$var[i],
      hoverinfo = "text",
      showlegend = TRUE
    )
}

# Limitar ejes de -1 a 1
fig <- fig %>%
  layout(
    scene = list(
      xaxis = list(title = "PC1", range = c(-1, 1)),
      yaxis = list(title = "PC2", range = c(-1, 1)),
      zaxis = list(title = "PC3", range = c(-1, 1))),
    legend = list(
      orientation = "h",
      x = 0.5,
      y = 1,
      xanchor = "center",
      yanchor = "bottom"),
    margin = list(l = 0, r = 0, b = 0, t = 20)
  )

# Muestra el gráfico interactivo
fig

Gráfico 3D de “individuos”

Las variables cualitativas permiten identificar posibles agrupaciones de departamentos según las sedes, como se muestra a continuación.

Code
# Extrae los componentes principales y añade la variable de sedes
components <- acp[["x"]]
components <- data.frame(components)
components <- cbind(components, sedes)

# Gráfico 3D interactivo usando los primeros tres componentes principales
fig <- plot_ly(
  components, 
  x = ~PC1, 
  y = ~PC2, 
  z = ~PC3, 
  color = ~sedes, 
  colors = c('#636EFA','#EF553B','#00CC96', '#FF6692', '#19D3F3')) %>%
  add_markers(size = 12) %>%
  layout(
    legend = list(
      orientation = "h",
      x = 0.5,
      y = 1,
      xanchor = "center",
      yanchor = "bottom"),
    margin = list(l = 0, r = 0, b = 0, t = 20))

# Muestra el gráfico interactivo
fig

Plano de variables e “individuos”

Un biplot muestra simultáneamente individuos y variables en el espacio de los componentes principales, permitiendo una interpretación conjunta de la estructura de los datos.

Code
# Biplot
fviz_pca_biplot(acp, axes = c(1, 2), col.ind = sedes, 
                geom.ind = "point", legend.title = "Sedes conectadas a internet", title = "", repel = TRUE) +
  theme(legend.position = "top")

Los departamentos con muy alto número de sedes conectadas a internet en ciertos años tienden a ubicarse en el extremo izquierdo del eje 1, lo que indica una asociación negativa con variables como deserción.

Code
# Biplot
fviz_pca_biplot(acp, axes = c(1, 2), col.ind = sedes, 
                geom.ind = "point", addEllipses = TRUE, 
                legend.title = "Sedes conectadas a internet", title = "", repel = TRUE) +
  theme(legend.position = "top")

Análisis de Correspondencias Múltiples (ACM)

De forma análoga al ACP, el ACM busca describir las asociaciones entre categorías de variables activas (Pardo 2020) y construir una tipología de individuos, basada en la semejanza: cuanto más características comparten, más próximos se consideran (Escofier 1992).

Para este ejercicio, se utilizará una tabla de datos con 67 observaciones que recoge distintos indicadores relacionados con el sueño y el bienestar general de las personas. Las variables incluidas abarcan tanto aspectos fisiológicos como conductuales:

Variable Descripción
ProblemasIniciar Problemas para iniciar el sueño.
ProblemasMantener Problemas para mantener el sueño.
ProblemasMadrugada Problemas de sueño en la madrugada.
NutricionIMC Indice de masa corporal
HoraSueño Horas de sueño día laboral
HoraCama Horas en la cama
Matutinidad Indice de matutinidad-Vespertinidad

Naturalmente, los valores de la tabla de datos deben ser codificados aunque no posean propiedades numéricas (ej. Sexo se codifica: F=1, M=2).

Code
# Cargar datos
sueño <- read_sav('Datos Sueños para Ejercicios.sav')

# Categorizar variables
sueño <- sueño %>% 
  mutate(Sexo = as.factor(Sexo),
         NutricionIMC = case_when(NutricionIMC < 18.5 ~ "Peso insuficiente",
                                  NutricionIMC >= 18.5 &  NutricionIMC <= 24.9 ~ "Peso saludable",
                                  NutricionIMC >= 25.0 &  NutricionIMC <= 29.9 ~ "Sobrepeso",
                                  NutricionIMC >= 30.0 ~ "Obesidad",
                                  TRUE ~ NA),
         NutricionIMC = factor(NutricionIMC, levels = c("Peso insuficiente", "Peso saludable", "Sobrepeso", "Obesidad"), ordered = TRUE),
         ProblemasIniciar = case_when(ProblemasIniciar %in% c(1, 2) ~ "No",
                                      ProblemasIniciar %in% c(3, 4) ~ "Leve",
                                      ProblemasIniciar == 5 ~ "Moderado",
                                      ProblemasIniciar >= 6 ~ "Severo",
                                      TRUE ~ NA),
         ProblemasIniciar = factor(ProblemasIniciar, levels = c("No", "Leve", "Moderado", "Severo"), ordered = TRUE),
         ProblemasMantener = case_when(ProblemasMantener %in% c(4, 5) ~ "No",
                                      ProblemasMantener %in% c(6, 7) ~ "Leve",
                                      ProblemasMantener %in% c(8, 9) ~ "Moderado",
                                      ProblemasMantener >= 10 ~ "Severo",
                                      TRUE ~ NA),
         ProblemasMantener = factor(ProblemasMantener, levels = c("No", "Leve", "Moderado", "Severo"), ordered = TRUE),
         ProblemasMadrugada = case_when(ProblemasMadrugada %in% c(0, 1) ~ "No",
                                       ProblemasMadrugada == 2 ~ "Leve",
                                       ProblemasMadrugada == 3 ~ "Moderado",
                                       ProblemasMadrugada >= 4 ~ "Severo",
                                       TRUE ~ NA),
         ProblemasMadrugada = factor(ProblemasMadrugada, levels = c("No", "Leve", "Moderado", "Severo"), ordered = TRUE),
         HoraSueño = case_when(HoraSueño <= 5 ~ "<5",
                               HoraSueño %in% c(6,7,8) ~ "6-8",
                               HoraSueño > 8 ~ ">8",
                               TRUE ~ NA),
         HoraSueño = factor(HoraSueño, levels = c("<5", "6-8", ">8"), ordered = TRUE)) %>% 
  drop_na(!where(is.numeric))

# Seleccionar variables de interés
sueño <- sueño %>% select(!where(is.numeric), HoraCama, Matutinidad)

str(sueño)
tibble [67 × 8] (S3: tbl_df/tbl/data.frame)
 $ Sexo              : Factor w/ 2 levels "F","M": 1 1 1 2 1 1 1 1 1 1 ...
 $ HoraSueño         : Ord.factor w/ 3 levels "<5"<"6-8"<">8": 1 1 2 1 1 1 2 1 2 2 ...
 $ ProblemasIniciar  : Ord.factor w/ 4 levels "No"<"Leve"<"Moderado"<..: 3 3 3 3 3 4 2 3 2 2 ...
 $ ProblemasMantener : Ord.factor w/ 4 levels "No"<"Leve"<"Moderado"<..: 4 4 4 3 4 3 4 4 4 4 ...
 $ ProblemasMadrugada: Ord.factor w/ 4 levels "No"<"Leve"<"Moderado"<..: 3 3 3 3 4 2 3 3 4 3 ...
 $ NutricionIMC      : Ord.factor w/ 4 levels "Peso insuficiente"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ HoraCama          : num [1:67] 4 7 7 5 5 7 9 6 8 9 ...
  ..- attr(*, "label")= chr "Horas en la cama"
  ..- attr(*, "format.spss")= chr "F8.2"
 $ Matutinidad       : num [1:67] 17 13 6 7 NA 15 14 22 NA NA ...
  ..- attr(*, "label")= chr "Indice de matutinidad-Vespertinidad"
  ..- attr(*, "format.spss")= chr "F8.2"

El objetivo del análisis es describir los hábitos alrededor del sueño de los individuos, a partir de las variables previamente presentadas, y explorar las diferencias entre los grupos que lo conforman.

Code
# Correr el modelo MCA
acm <- MCA(sueño,
           # Variables suplementarias Cualitativas
           quali.sup = c(1, 6), 
           # Variables suplementarias Cuantitativas
           quanti.sup = c(7, 8), graph = FALSE)

acm$eig
       eigenvalue percentage of variance cumulative percentage of variance
dim 1  0.49634071              18.048753                          18.04875
dim 2  0.41859109              15.221494                          33.27025
dim 3  0.34994926              12.725427                          45.99567
dim 4  0.29422120              10.698953                          56.69463
dim 5  0.27914664              10.150787                          66.84541
dim 6  0.24391641               8.869688                          75.71510
dim 7  0.19892035               7.233467                          82.94857
dim 8  0.18074629               6.572592                          89.52116
dim 9  0.15112185               5.495340                          95.01650
dim 10 0.08535814               3.103933                          98.12043
dim 11 0.05168808               1.879566                         100.00000

La dimensión 1 explica el 18,04% de la varianza total, un valor modesto pero habitual en el ACM con muchas variables categóricas (Escofier 1992). En este caso, no hay dimensiones dominantes; se necesitan al menos cinco para alcanzar cerca del 65% de la varianza.

Como en el ejercicio de ACP, la función explor() permite visualizar algunos elementos:

  • La contribución de una variable, que es la suma de las contribuciones de sus categorías a un factor. Al ordenar las variables según su contribución decreciente, es posible identificar las más asociadas a cada dimensión (Escofier 1992).

  • En el análisis de las coordenadas de las categorías, se recomienda empezar por seleccionar los factores sobre los que las categorías de las variables ordenadas se encuentran en su orden natural (Escofier 1992).

  • El coseno cuadrado, que se utiliza para evaluar la calidad de las proyecciones. Su valor sobre un plano es la suma de los cosenos cuadrados de los ejes (Pardo 2020).

Code
# Gráfico interactivo
explor(acm)

Shiny applications not supported in static R Markdown documents

Code
# Contribución de variables
acm$var$eta2
                       Dim 1       Dim 2      Dim 3      Dim 4     Dim 5
HoraSueño          0.1273746 0.009451718 0.47667130 0.50631003 0.1200599
ProblemasIniciar   0.3384060 0.375272215 0.22092975 0.52311359 0.4138665
ProblemasMantener  0.8385845 0.587925588 0.04099126 0.06818816 0.4648566
ProblemasMadrugada 0.6809978 0.701714821 0.66120471 0.07927301 0.1178035

El factor 1 ordena las categorías de problemas para mantener el sueño y problemas de sueño en la madrugada, el factor 2 ayuda a diferenciar aquellas personas que tienen severos problemas para iniciar el sueño de quienes no, mientras que el factor 3 ordena las modalidades de horas de sueño día laboral.

Cabe mencionar que el primer plano factorial presenta el efecto Guttman o efecto herradura, ya que muestra en forma de parábola (o forma de U) las categorías de la variable e individuos. Como se observa, el primer eje opone los problemas de sueño extremos (no vs. severo) y el segundo eje, los medios a los extremos (leve/moderado vs. no/severo).

Code
# Variables suplementarias

## Cualitativas
acm$quali.sup$coord

## Cuantitativas
acm$quanti.sup$coord
                        Dim 1       Dim 2       Dim 3       Dim 4       Dim 5
F                  0.49564414 -0.06909078  0.14419921  0.09018626  0.06775936
M                 -0.54211078  0.07556804 -0.15771789 -0.09864122 -0.07411180
Peso insuficiente  0.23856755 -0.37022548 -0.33333884  0.18335440  0.35989815
Peso saludable    -0.03771636  0.05150491  0.05360913 -0.04252740 -0.06401643
Sobrepeso          0.17960683 -0.17860672 -0.26392187  0.33098383  0.37238697
                  Dim 1        Dim 2      Dim 3       Dim 4      Dim 5
HoraCama     0.08401619 -0.048213846 0.52966922  0.17933904 -0.1836327
Matutinidad -0.08925877 -0.006594432 0.03693762 -0.04967632 -0.1534797

En cuanto a variables suplementarias o ilustrativas, que se usan para estudiar su relación con la estructura factorial encontrada sin influir en ella, se encontró que los hombres se encuentran cercanos a problemas leves para iniciar y mantener el sueño.

Adicionalmente, el número de horas en la cama tiene una relación moderada con el factor 3. Al contrario, matutinidad se encuentra cercana al punto de origen, lo que quiere decir que esta variable no resulta muy informativa.

Code
# Extrae las coordenadas y añade el nombre de la variable en una columna
coordinates <- acm$var$coord %>% as.data.frame()
coordinates$Cat <- gsub(".*_(.*)$", "\\1", row.names(coordinates))
coordinates$Var <- gsub("(.*)_(.*)$", "\\1", row.names(coordinates))
coordinates <- coordinates %>% 
  mutate(Var = ifelse(Var %in% unique(sueño$HoraSueño), "HoraSueño", Var))

# Extraer coordenadas de las variables cualitativas y cuantitativas suplementarias
quali_coords <- acm$quali.sup$coord %>% as.data.frame()
quanti_coords <- acm$quanti.sup$coord %>% as.data.frame()

# Extraer coordenadas de individuos
ind_coords <- acm$ind$coord %>% as.data.frame()

# Gráfico

## Establecer paleta de colores
palette <- c(
  wes_palette("Rushmore", type = "discrete")[3:5],
  wes_palette("GrandBudapest1", type = "discrete")[2:4],
  wes_palette("BottleRocket2", type = "discrete")[4:5]
)

## Objeto
fig <- plot_ly(
  coordinates, 
  x = ~`Dim 1`, 
  y = ~`Dim 2`, 
  z = ~`Dim 3`, 
  type = "scatter3d",
  mode = "markers+text",
  text = ~Cat,
  textposition = "top center",
  textfont = list(size = 14),
  marker = list(size = 7, symbol = 'cross'),
  color = ~Var,
  colors = palette,
  showlegend = TRUE
)

## Añadir variables suplementarias
fig <- fig %>% 
  # Añadir las coordenadas cualitativas
  add_trace(
    data = quali_coords,
    x = ~`Dim 1`, 
    y = ~`Dim 2`, 
    z = ~`Dim 3`,
    type = "scatter3d",
    mode = "markers+text",
    text = rownames(quali_coords),
    textposition = "top center",
    textfont = list(size = 14, color = "#0000CC"),
    marker = list(size = 4, symbol = 'diamond', color = "#0000CC"),
    name = "Suplementarias (Cuali)",
    inherit = FALSE
  ) %>%
  # Añadir las coordenadas cuantitativas
  add_trace(
    data = quanti_coords,
    x = ~`Dim 1`, 
    y = ~`Dim 2`, 
    z = ~`Dim 3`,
    type = "scatter3d",
    mode = "lines+text",
    text = rownames(quanti_coords),
    textposition = "top center",
    textfont = list(size = 14, color = "#660099"),
    line = list(color = "#660099", width = 3),
    name = "Suplementarias (Cuanti)",
    inherit = FALSE
  )

## Añadir individuos
fig <- fig %>% 
  # Añadir las coordenadas cualitativas
  add_trace(
    data = ind_coords,
    x = ~`Dim 1`, 
    y = ~`Dim 2`, 
    z = ~`Dim 3`,
    type = "scatter3d",
    mode = "markers",
    marker = list(size = 4, symbol = 'circle-open', color = "black"),
    name = "Individuos",
    inherit = FALSE
  ) 

## Últimos detalles
fig <- fig %>%
  layout(
    legend = list(
      orientation = "h",
      x = 0.5, y = 1.05,
      xanchor = "center",
      yanchor = "bottom",
      font = list(size = 18),
      bordercolor = 'rgba(200,200,200,0.5)',
      borderwidth = 1
    ),
    margin = list(l = 10, r = 10, b = 10, t = 10)
  )

## Mostrar
fig

Referencias

Escofier, Brigitte. 1992. Análisis Factoriales Simples y Múltiples: Objetivos, Métodos e Interpretación. Bilbao: Universidad del País Vasco.
Ministerio de Educación Nacional [MEN]. 2024. MEN_ESTADISTICAS_EN_EDUCACION_EN_PREESCOLAR, BÁSICA Y MEDIA_POR_DEPARTAMENTO.” https://www.datos.gov.co/Educaci-n/MEN_ESTADISTICAS_EN_EDUCACION_EN_PREESCOLAR-B-SICA/ji8i-4anb/about_data.
Pardo, Campo Elías. 2020. “Estadística Descriptiva Multivariada.” https://repositorio.unal.edu.co/handle/unal/79914.