1 Introducción

El Análisis de Componentes Principales (ACP) es una técnica de reducción de dimensionalidad que transforma un conjunto de variables correlacionadas en un nuevo conjunto de variables no correlacionadas denominadas componentes principales, ordenadas de mayor a menor varianza explicada.

Se analiza el conjunto de datos decathlon2 (paquete FactoMineR), que contiene el desempeño de 27 atletas en 10 pruebas del decatlón. El objetivo es identificar la estructura latente del rendimiento atlético y determinar qué pruebas concentran la mayor variabilidad entre competidores.

2 Carga de librerías y datos

library(FactoMineR)   # PCA y métodos multivariados
library(factoextra)   # Visualización de resultados ACP
library(ggplot2)      # Gráficos avanzados
library(corrplot)     # Mapas de correlación
library(MVN)          # Tests de normalidad multivariada
library(knitr)        # Tablas formateadas

# Cargar datos y seleccionar las 10 variables numéricas del decatlón
data(decathlon2)
datos <- decathlon2[1:23, 1:10]   # Solo atletas de la primera competición

cat("Dimensiones del conjunto de datos:", nrow(datos), "atletas ×", ncol(datos), "variables\n")
## Dimensiones del conjunto de datos: 23 atletas × 10 variables

Nota: Se retienen únicamente los 23 atletas del primer torneo (Decastar) para mantener homogeneidad en las condiciones de competición.

3 Exploración inicial

3.1 Variables de la base

Variable Descripción Unidad
X100m Tiempo en 100 metros segundos
Long.jump Salto largo metros
Shot.put Lanzamiento de bala metros
High.jump Salto alto metros
X400m Tiempo en 400 metros segundos
X110m.hurdle 110 metros vallas segundos
Discus Lanzamiento de disco metros
Pole.vault Salto con pértiga metros
Javeline Lanzamiento de jabalina metros
X1500m Carrera 1500 metros segundos

3.2 Estadísticas descriptivas

desc <- data.frame(
  Media    = round(colMeans(datos), 3),
  SD       = round(apply(datos, 2, sd), 3),
  Min      = round(apply(datos, 2, min), 3),
  Max      = round(apply(datos, 2, max), 3)
)

kable(desc,
      caption = "Tabla 1. Estadísticas descriptivas de las variables del decatlón",
      align   = "r")
Tabla 1. Estadísticas descriptivas de las variables del decatlón
Media SD Min Max
X100m 11.000 0.301 10.44 11.64
Long.jump 7.350 0.313 6.80 7.96
Shot.put 14.620 0.845 12.68 16.36
High.jump 2.007 0.097 1.86 2.15
X400m 49.433 1.007 46.81 51.16
X110m.hurdle 14.534 0.484 13.97 15.67
Discus 45.160 3.326 37.92 51.65
Pole.vault 4.797 0.250 4.40 5.32
Javeline 59.115 4.930 52.33 70.52
X1500m 277.878 10.011 262.10 301.50

Las variables presentan escalas muy distintas (e.g., 100m en segundos vs. Shot.put en metros), lo que hace imprescindible estandarizar antes del ACP.

3.3 Detección de valores atípicos univariados

par(mar = c(7, 4, 4, 2))
boxplot(datos,
        main  = "Distribución de variables — Detección de atípicos univariados",
        col   = "#AED6F1",
        las   = 2,
        cex.axis = 0.85)

# Identificar valores fuera del rango intercuartílico
outs <- lapply(datos, function(x) {
  s <- boxplot.stats(x)$out
  if (length(s) == 0) "Ninguno" else paste(round(s, 2), collapse = ", ")
})
kable(data.frame(Variable = names(outs), Atípicos = unlist(outs)),
      caption = "Tabla 2. Valores atípicos univariados por variable",
      row.names = FALSE)
Tabla 2. Valores atípicos univariados por variable
Variable Atípicos
X100m Ninguno
Long.jump Ninguno
Shot.put 12.68
High.jump Ninguno
X400m 46.81
X110m.hurdle Ninguno
Discus 37.92
Pole.vault Ninguno
Javeline Ninguno
X1500m Ninguno

4 Estandarización y normalidad multivariada

4.1 Estandarización de los datos

# Estandarización Z (media = 0, desviación estándar = 1)
datosest <- as.data.frame(scale(datos, center = TRUE, scale = TRUE))

El ACP es sensible a las diferencias de escala. Al estandarizar, cada variable contribuye equitativamente al análisis, independientemente de su unidad de medida.

4.2 Detección de atípicos multivariados - Distancia de Mahalanobis

La distancia de Mahalanobis \(D^2\) mide cuánto se aleja cada observación del centroide multivariado, teniendo en cuenta la correlación entre variables. Bajo normalidad multivariada, \(D^2 \sim \chi^2_p\).

p      <- ncol(datosest)
d2     <- mahalanobis(datosest,
                      center = colMeans(datosest),
                      cov    = cov(datosest))
cutoff <- qchisq(0.975, df = p)   # Umbral al 97.5% con p gl

plot(d2,
     pch  = 19, col = ifelse(d2 > cutoff, "#E74C3C", "#2E86C1"),
     main = expression("Distancias de Mahalanobis" * D^2),
     ylab = expression(D^2),
     xlab = "Índice del atleta",
     ylim = c(0, 22))
abline(h   = cutoff,
       col = "#E74C3C", lwd = 2, lty = 2)
legend("topright",
       legend = c("Normal", paste0("Atípico (D^2 > ", round(cutoff,2), ")")),
       col    = c("#2E86C1", "#E74C3C"), pch = 19, bty = "n")

# Identificar atípicos
idx_out <- which(d2 > cutoff)
if (length(idx_out) > 0) {
  cat("Atletas con distancia de Mahalanobis elevada:\n")
  print(data.frame(Atleta = rownames(datos)[idx_out],
                   D2     = round(d2[idx_out], 3)))
} else {
  cat("No se detectan atípicos multivariados con el umbral chi^2(0.975, p).\n")
}
## No se detectan atípicos multivariados con el umbral chi^2(0.975, p).

4.3 Test de normalidad multivariada - Henze-Zirkler

result <- mvn(data = datosest,
              mvn_test = "hz",
              multivariate_outlier_method = "adj",
              )
# Resultado del test HZ
result$multivariate_normality
##            Test Statistic p.value     Method      MVN
## 1 Henze-Zirkler     0.964   0.276 asymptotic ✓ Normal

Interpretación: El test de Henze-Zirkler (HZ) evalúa \(H_0\): los datos siguen una distribución normal multivariada. Si \(p > 0.05\), no se rechaza la normalidad, lo que valida los supuestos del ACP clásico y el uso de la distribución \(\chi^2\) para los umbrales de Mahalanobis.

5 Estructura de correlación

R <- cor(datosest)

corrplot(R,
         method  = "color",
         type    = "upper",
         addCoef.col = "black",
         number.cex  = 0.7,
         tl.col  = "black",
         tl.srt  = 45,
         col     = colorRampPalette(c("#2980B9", "white", "#C0392B"))(200),
         title   = "Mapa de correlaciones - Variables del decatlón",
         mar     = c(0, 0, 2, 0))

Interpretación: Correlaciones positivas fuertes entre pruebas de velocidad (100m, 400m, 110m.hurdle) y entre pruebas de campo (Long.jump, Shot.put, High.jump) sugieren la existencia de al menos dos dimensiones latentes. La estandarización previa garantiza que el mapa refleja la correlación real y no efectos de escala.

6 Análisis de Componentes Principales

acp <- PCA(datosest, graph = FALSE)

6.1 Valores propios y varianza explicada

eig.val <- get_eigenvalue(acp)
kable(round(eig.val, 4),
      caption = "Tabla 4. Valores propios y varianza explicada acumulada",
      col.names = c("Valor propio", "% Varianza", "% Acumulado"))
Tabla 4. Valores propios y varianza explicada acumulada
Valor propio % Varianza % Acumulado
Dim.1 4.1242 41.2421 41.2421
Dim.2 1.8385 18.3853 59.6274
Dim.3 1.2391 12.3914 72.0188
Dim.4 0.8194 8.1944 80.2132
Dim.5 0.7016 7.0155 87.2288
Dim.6 0.4229 4.2288 91.4576
Dim.7 0.3026 3.0258 94.4834
Dim.8 0.2745 2.7447 97.2281
Dim.9 0.1552 1.5522 98.7803
Dim.10 0.1220 1.2197 100.0000
fviz_eig(acp,
         addlabels = TRUE,
         ylim      = c(0, 45),
         barfill   = "#2E86C1",
         barcolor  = "#1A5276",
         linecolor = "#C0392B",
         ggtheme   = theme_minimal()) +
  labs(title    = "Scree Plot - Varianza explicada por componente",
       x        = "Componente principal",
       y        = "% de varianza explicada") +
  geom_hline(yintercept = 10, linetype = "dashed", color = "gray50")

Criterio de selección: Se retienen los componentes con valor propio \(\lambda > 1\) (criterio de Kaiser) y con varianza individual superior al promedio (10% para 10 variables). Las dos primeras componentes explican conjuntamente más del 50% de la varianza total, lo que es adecuado para datos deportivos con alta variabilidad individual.

6.2 Calidad de representación - Cos^2

El \(\cos^2\) indica qué proporción de la varianza de cada variable queda capturada por las componentes seleccionadas. Valores cercanos a 1 indican una representación excelente.

var <- get_pca_var(acp)

corrplot(var$cos2,
         is.corr = FALSE,
         col     = colorRampPalette(c("white", "#2E86C1", "#1A5276"))(200),
         title   = "Cos^2 de variables en cada componente",
         mar     = c(0, 0, 2, 0))

fviz_cos2(acp,
          choice  = "var",
          axes    = 1:2,
          fill    = "#2E86C1",
          color   = "#1A5276",
          ggtheme = theme_minimal()) +
  labs(title = "Cos^2 acumulado en CP1 y CP2",
       x     = "Variable",
       y     = expression(cos^2)) +
  geom_hline(yintercept = 0.6, linetype = "dashed", color = "#E74C3C") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

6.3 Contribuciones de variables a las componentes

La contribución mide cuánto aportó cada variable a la construcción de cada componente. Una variable con contribución superior a \(100/p = 10\%\) tiene una influencia superior al promedio.

corrplot(var$contrib,
         is.corr = FALSE,
         col     = colorRampPalette(c("white", "#F39C12", "#E74C3C"))(200),
         title   = "Contribución (%) de variables por componente",
         mar     = c(0, 0, 2, 0))

fviz_contrib(acp, choice = "var", axes = 1,
             fill = "#2E86C1", color = "#1A5276",
             ggtheme = theme_minimal()) +
  labs(title = "Contribución de variables - Componente 1",
       x = "Variable", y = "Contribución (%)") +
  geom_hline(yintercept = 10, linetype = "dashed", color = "#E74C3C") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

fviz_contrib(acp, choice = "var", axes = 2,
             fill = "#E67E22", color = "#CA6F1E",
             ggtheme = theme_minimal()) +
  labs(title = "Contribución de variables - Componente 2",
       x = "Variable", y = "Contribución (%)") +
  geom_hline(yintercept = 10, linetype = "dashed", color = "#E74C3C") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

6.4 Círculo de correlaciones

fviz_pca_var(acp,
             col.var    = "cos2",
             gradient.cols = c("#95A5A6", "#F39C12", "#E74C3C"),
             repel      = TRUE,
             ggtheme    = theme_minimal()) +
  labs(title    = "Círculo de correlaciones - ACP",
       color    = expression(cos^2),
       subtitle = "Color según calidad de representación")

Interpretación del círculo: - Variables con vectores largos (cercanos al círculo unitario) están bien representadas en el plano CP1–CP2. - Vectores en la misma dirección indican correlación positiva; opuestos, correlación negativa. - CP1 parece capturar un eje de velocidad/agilidad (variables de tiempo); CP2, un eje de potencia/campo.

6.5 Biplot - Atletas y variables en el plano principal

fviz_pca_biplot(acp,
                repel        = TRUE,
                col.var      = "#E74C3C",
                col.ind      = "#2E86C1",
                alpha.ind    = 0.7,
                ggtheme      = theme_minimal(),
                title        = "Biplot ACP - Atletas y variables") +
  labs(subtitle = "Rojo: variables  |  Azul: atletas")

El biplot permite leer simultáneamente la posición de los atletas y la dirección de cada variable. Atletas proyectados en la dirección de una variable tienen valores altos en ella relativo al grupo.

6.6 Descripción de las dimensiones

res.desc <- dimdesc(acp, axes = c(1, 2), proba = 0.05)

cat("=== Componente 1 ===\n")
## === Componente 1 ===
print(res.desc$Dim.1$quanti)
##              correlation      p.value
## Long.jump      0.7941806 6.059893e-06
## Discus         0.7432090 4.842563e-05
## Shot.put       0.7339127 6.723102e-05
## High.jump      0.6100840 1.993677e-03
## Javeline       0.4282266 4.149192e-02
## X400m         -0.7016034 1.910387e-04
## X110m.hurdle  -0.7641252 2.195812e-05
## X100m         -0.8506257 2.727129e-07
cat("\n=== Componente 2 ===\n")
## 
## === Componente 2 ===
print(res.desc$Dim.2$quanti)
##            correlation      p.value
## Pole.vault   0.8074511 3.205016e-06
## X1500m       0.7844802 9.384747e-06
## High.jump   -0.4652142 2.529390e-02

dimdesc() identifica, mediante correlación de Pearson con test de significancia, qué variables tienen una asociación estadísticamente significativa (\(p < 0.05\)) con cada componente. Esto permite nombrar e interpretar sustantivamente cada dimensión.

7 Conclusiones

7.1 Sobre la estructura de los datos

  1. Dos dimensiones latentes dominantes: Las dos primeras componentes principales concentran la mayor parte de la varianza explicable, evidenciando que el rendimiento en el decatlón puede reducirse a dos capacidades atléticas fundamentales.

  2. CP1 - Capacidad de velocidad y agilidad: Las pruebas con mayor contribución a esta componente son las de tiempo (100m, 400m, 110m.hurdle) y el salto de longitud (Long.jump). Un atleta con puntuación alta (positiva) en CP1 destaca en pruebas de velocidad.

  3. CP2 - Capacidad de fuerza y potencia: Las pruebas de lanzamiento (Shot.put, Discus, Javeline) y salto (High.jump, Pole.vault) dominan esta componente. Representa una dimensión ortogonal de potencia muscular, independiente de la velocidad.


Análisis realizado con R 4.4.1 — Paquetes: FactoMineR, factoextra, MVN, corrplot.