En este caso de estudio se analiza un conjunto de datos simulado de deportistas de nivel superior. El propósito es identificar perfiles deportivos a partir de variables relacionadas con la condición física, el desempeño atlético, los aspectos mentales y el rendimiento académico.
Para ello, se consideran variables como experiencia deportiva, horas de entrenamiento, resistencia, fuerza, velocidad, agilidad, concentración, disciplina, motivación, manejo del estrés, promedio académico y rendimiento competitivo. Debido a que no se cuenta con una variable dependiente, se emplea un enfoque de aprendizaje no supervisado mediante K-Means y K-Medians.
Aquí la descripción específica de las variables de interés:
Los datos cumplen con los requisitos generales para modelos de clustering, sin embargo se transforman los datos atípicos y correlacionados para mejorar eficiencia en la construcción del modelo.
Los datos se encuentran en https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/datos/datos_deportistas_clustering.csv .
El caso de estudio se puede ver en el portal de rpubs.com en https://rpubs.com/rpizarrog/1446970 .
Las funciones utilizadas se encuentran en github.com en https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/R%20MarkDown/funciones/funciones%20para%20K-Means%20y%20K%20Medians.R .
Identificar grupos de deportistas con características similares a partir de variables físico-atléticas, mentales y académicas, utilizando modelos de clustering K-Means y K-Medians.
El propósito es reconocer perfiles deportivos que permitan diferenciar clases de deportistas tentativamente novatos, intermedios, expertos y de alto rendimiento.
Se hace una comparación entre los dos modelos.
library(readr)
library(ggplot2)
library(patchwork)
library (psych) # Para describir datos
library(PerformanceAnalytics) # Para Correlaciones
# url <- "../funciones/funciones para K-Means.R" # local
url <- "https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/R%20MarkDown/funciones/funciones%20para%20K-Means%20y%20K%20Medians.R"
source(url)
set.seed(2026)
Se cargan los registros de deportistas con la función f_cargar_datos(url). Los datos_originales vienen con la columna del n[umero de deportista y una variable columna etiqueta al final, estas se omiten para efecto de modelos de clustering.
Las variables de interés son 14 que se utilizarán para modelos clustering y son: “edad”, “experiencia”, “entrenamiento”, “resistencia”, “fuerza”, “velocidad”, “agilidad”, “flexibilidad”, “concentracion”, “disciplina”, “motivacion”, “manejo_estres”, “promedio”, “competitividad”
# url <- "../datos/datos_mil_estudiantes_k-means.csv" # local
url <- "https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/datos/datos_deportistas_clustering.csv" # WEB
datos_originales <- f_cargar_datos(url)
datos <- datos_originales[,c(-1, -ncol(datos_originales))]
f_visualizar_head_tail_reducido_word(datos)
edad | experiencia | entrenamiento | resistencia | ... | motivacion | manejo_estres | promedio | competitividad |
|---|---|---|---|---|---|---|---|---|
21.5 | 5.2 | 19.7 | 69.8 | ... | 77.1 | 87.9 | 88.5 | 76.9 |
18.3 | 2.3 | 6.9 | 45 | ... | 47.2 | 45.8 | 81.8 | 27.5 |
18.2 | 1.1 | 5.2 | 32.6 | ... | 54.2 | 39.5 | 82.3 | 41.9 |
21.7 | 4.4 | 9.3 | 58.9 | ... | 68.2 | 67.8 | 78.5 | 63.9 |
25 | 6.4 | 15.7 | 68 | ... | 86.8 | 69.9 | 84 | 69 |
21.9 | 3.8 | 9.5 | 60.9 | ... | 66.2 | 77.4 | 82.5 | 59.5 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
19.8 | 4 | 7.7 | 58.9 | ... | 64.4 | 73.3 | 87.6 | 62.3 |
18.7 | 0.6 | 5.6 | 22.8 | ... | 62.1 | 57.5 | 78.6 | 47.8 |
22 | 4.8 | 13.5 | 72.4 | ... | 86.1 | 72.9 | 87.1 | 79.7 |
19 | 3.5 | 5.6 | 60.3 | ... | 73 | 70.5 | 81.8 | 58.3 |
20.2 | 1.6 | 2 | 47.1 | ... | 62.2 | 65.5 | 81.7 | 56.5 |
17 | 1.3 | 2.9 | 39.5 | ... | 73.9 | 61.4 | 76.4 | 39.4 |
Se manda llamar la función f_describir_datos() y se presentan los estadísticos descriptivos de cada variable.
f_describir_datos(datos)
## $describe
## vars n mean sd median trimmed mad min max range
## edad 1 1000 20.28 1.82 20.20 20.20 1.93 17.0 25.0 8.0
## experiencia 2 1000 4.13 2.85 3.70 3.89 3.26 0.0 12.0 12.0
## entrenamiento 3 1000 11.67 6.62 10.60 11.14 7.12 1.0 30.0 29.0
## resistencia 4 1000 63.17 17.53 63.40 63.18 20.31 22.8 99.4 76.6
## fuerza 5 1000 64.40 17.40 64.70 64.51 19.87 21.0 100.0 79.0
## velocidad 6 1000 65.38 17.32 65.75 65.49 20.02 22.7 100.0 77.3
## agilidad 7 1000 65.28 17.08 65.45 65.42 20.02 27.3 100.0 72.7
## flexibilidad 8 1000 64.00 14.41 64.30 64.36 15.42 24.3 95.2 70.9
## concentracion 9 1000 69.31 15.35 69.90 69.59 17.49 29.0 100.0 71.0
## disciplina 10 1000 71.28 15.02 71.35 71.44 17.27 32.0 100.0 68.0
## motivacion 11 1000 73.52 14.22 73.55 73.88 15.79 37.8 100.0 62.2
## manejo_estres 12 1000 66.93 15.46 67.50 67.16 16.61 26.7 100.0 73.3
## promedio 13 1000 82.59 6.02 82.50 82.53 6.23 70.0 100.0 30.0
## competitividad 14 1000 63.93 17.78 64.15 63.90 20.39 23.1 100.0 76.9
## skew kurtosis se
## edad 0.36 -0.43 0.06
## experiencia 0.65 -0.33 0.09
## entrenamiento 0.64 -0.26 0.21
## resistencia -0.03 -0.89 0.55
## fuerza -0.08 -0.85 0.55
## velocidad -0.04 -0.88 0.55
## agilidad -0.07 -0.86 0.54
## flexibilidad -0.17 -0.63 0.46
## concentracion -0.14 -0.82 0.49
## disciplina -0.09 -0.83 0.48
## motivacion -0.18 -0.74 0.45
## manejo_estres -0.13 -0.60 0.49
## promedio 0.10 -0.39 0.19
## competitividad -0.02 -0.83 0.56
##
## $structure
## [1] "'data.frame':\t1000 obs. of 14 variables:\n $ edad : num 21.5 18.3 18.2 21.7 25 21.9 24 22.4 19.9 20.5 ...\n $ experiencia : num 5.2 2.3 1.1 4.4 6.4 3.8 11 6.9 1.2 2.8 ...\n $ entrenamiento : num 19.7 6.9 5.2 9.3 15.7 9.5 22.1 18.6 8.1 12.9 ...\n $ resistencia : num 69.8 45 32.6 58.9 68 60.9 87.1 79.4 64.1 59.8 ...\n $ fuerza : num 75.7 31.7 33.5 63.2 79.3 70.9 84.7 72.4 62.9 63.2 ...\n $ velocidad : num 80 58 53.7 65.3 73.3 63.3 84.8 82.2 58.4 73.4 ...\n $ agilidad : num 79.3 53.4 35.2 57.8 77.7 66.3 90.9 86.1 59.3 64.6 ...\n $ flexibilidad : num 61.9 46.7 57.1 69.7 77.1 75.1 80.5 74.5 60.2 65 ...\n $ concentracion : num 76.5 47.6 48.1 65.2 71.6 65.6 99.4 85.3 62.4 58.1 ...\n $ disciplina : num 85 52.5 62.6 67 84.9 62.4 94.2 86.5 66.4 73.4 ...\n $ motivacion : num 77.1 47.2 54.2 68.2 86.8 66.2 86.2 95.9 68.2 65.1 ...\n $ manejo_estres : num 87.9 45.8 39.5 67.8 69.9 77.4 97.1 77.2 73.2 74.1 ...\n $ promedio : num 88.5 81.8 82.3 78.5 84 82.5 88.8 84.5 87.1 81.1 ...\n $ competitividad: num 76.9 27.5 41.9 63.9 69 59.5 95.8 79.3 69.5 47.3 ..."
Es recomendable detectar valores extremos outliers, analizar correlaciones entre variables físico-atléticas y estandarizar los datos para evitar que una variable domine el cálculo de distancias.
variables <- c("edad", "experiencia", "entrenamiento", "resistencia", "fuerza", "velocidad",
"agilidad", "flexibilidad", "concentracion", "disciplina", "motivacion", "manejo_estres",
"promedio", "competitividad")
Se identifican datos atípicos en el conjunto de datos en cada variable, mostrando los diagramas de caja. Solo se detecta que en la variable promedio existen atípicos por lo que se procede a transformas los valores encontrados como outliers por el valor de la mediana de esta variable en particular.
# BOXPLOT POR CADA VARIABLE
f_atipicos(
datos = datos,
variables = variables,
ncol = 3
)
Transformar valores atípicos por las medianas de cada variable y se almacena en datos_limpios.
variables_clustering <- variables
resultado_atipicos <- f_transformar_atipicos(
datos = datos,
variables = variables,
metodo = "mediana"
)
## Resumen de transformación de valores atípicos:
## variable limite_inferior limite_superior n_atipicos valor_reemplazo
## 25% edad 15.0000 25.4000 0 20.20
## 25%1 experiencia -5.1500 12.8500 0 3.70
## 25%2 entrenamiento -8.6500 31.1500 0 10.60
## 25%3 resistencia 5.8000 119.6000 0 63.40
## 25%4 fuerza 10.1000 118.3000 0 64.70
## 25%5 velocidad 11.4750 119.6750 0 65.75
## 25%6 agilidad 11.3125 119.0125 0 65.45
## 25%7 flexibilidad 23.2125 106.1125 0 64.30
## 25%8 concentracion 22.0125 116.9125 0 69.90
## 25%9 disciplina 24.9500 118.1500 0 71.35
## 25%10 motivacion 31.0625 117.5625 0 73.55
## 25%11 manejo_estres 22.3625 112.0625 0 67.50
## 25%12 promedio 65.9500 99.1500 2 82.50
## 25%13 competitividad 8.6875 118.7875 0 64.15
## metodo
## 25% mediana
## 25%1 mediana
## 25%2 mediana
## 25%3 mediana
## 25%4 mediana
## 25%5 mediana
## 25%6 mediana
## 25%7 mediana
## 25%8 mediana
## 25%9 mediana
## 25%10 mediana
## 25%11 mediana
## 25%12 mediana
## 25%13 mediana
datos_limpios <- resultado_atipicos$datos_limpios
resumen_atipicos <- resultado_atipicos$resumen_atipicos
Con la instrucción chart.Correlation(), se identifican variables correlacionadas, el gráfico de correlación de Pearson no detecta correlaciones fuertes de tal manera que los datos quedan sin hacer transformaciones por el concepto de correlación entre variables. Los datos limpios quedan sin modificaciones.
La idea de encontrar correlaciones es que si hay fuertes relaciones entre variables que participan en el modelo de clustering es recomendable eliminar alguna de ellas o juntar aritm[eticamente como las estrategias que se describieron el el capítulo de regresiones.
chart.Correlation(datos_limpios, histogram = TRUE)
Se estandarizan todas la variables numéricas y se dejan en un conjunto de datos llamado datos_estandarizados. Se muestran los primeros y últimos registros de los datos estandarizados al igual que las primeras cuatro y últimas cuatro columnas.
resultados <- f_estandarizar(datos_limpios)
datos_estandarizados <- resultados$datos_estandarizados
f_visualizar_head_tail_reducido_word(f_redondear_datos(datos_estandarizados, 4))
edad | experiencia | entrenamiento | resistencia | ... | motivacion | manejo_estres | promedio | competitividad |
|---|---|---|---|---|---|---|---|---|
0.6706 | 0.3745 | 1.2125 | 0.3784 | ... | 0.2516 | 1.3565 | 0.995 | 0.7293 |
-1.0906 | -0.6419 | -0.7214 | -1.036 | ... | -1.8513 | -1.3665 | -0.1265 | -2.0489 |
-1.1457 | -1.0624 | -0.9783 | -1.7433 | ... | -1.359 | -1.774 | -0.0428 | -1.2391 |
0.7807 | 0.0941 | -0.3588 | -0.2433 | ... | -0.3744 | 0.0564 | -0.6789 | -0.0018 |
2.5969 | 0.795 | 0.6082 | 0.2757 | ... | 0.9338 | 0.1923 | 0.2418 | 0.285 |
0.8907 | -0.1162 | -0.3286 | -0.1292 | ... | -0.515 | 0.6774 | -0.0093 | -0.2493 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
-0.2651 | -0.0461 | -0.6006 | -0.2433 | ... | -0.6416 | 0.4122 | 0.8444 | -0.0918 |
-0.8705 | -1.2377 | -0.9179 | -2.3022 | ... | -0.8034 | -0.6097 | -0.6621 | -0.9073 |
0.9458 | 0.2343 | 0.2758 | 0.5267 | ... | 0.8846 | 0.3863 | 0.7607 | 0.8867 |
-0.7054 | -0.2213 | -0.9179 | -0.1634 | ... | -0.0368 | 0.2311 | -0.1265 | -0.3168 |
-0.0449 | -0.8872 | -1.4618 | -0.9163 | ... | -0.7964 | -0.0923 | -0.1432 | -0.418 |
-1.8061 | -0.9924 | -1.3258 | -1.3497 | ... | 0.0265 | -0.3575 | -1.0304 | -1.3797 |
Se construye el modelo K-Means con la función f_crear_KMeans() con los datos estandarizados.
modelo_KMeans <- f_crear_KMeans(datos_estandarizados, variables, centers = 4)
Se observan los clusteres y los centroides
datos_estandarizados$cluster_kmeans <- modelo_KMeans$cluster
# Mostrar resultados
# print(head(datos_estandarizados))
# print(tail(datos_estandarizados))
cat("\nCentroides finales:\n")
##
## Centroides finales:
print(modelo_KMeans$centers)
## edad experiencia entrenamiento resistencia fuerza velocidad
## 1 -0.1169515 -0.2155271 -0.2363542 -0.08749827 -0.06352975 -0.1011065
## 2 -0.9485227 -1.0709930 -1.0135623 -1.18648024 -1.20247418 -1.1649945
## 3 0.7506105 0.8486300 0.7949356 0.86597719 0.85662751 0.8771282
## 4 1.3003327 1.7618586 1.8011783 1.58627083 1.56694200 1.5495284
## agilidad flexibilidad concentracion disciplina motivacion manejo_estres
## 1 -0.07517053 -0.06716854 -0.06839289 -0.06651786 -0.0891350 -0.06144918
## 2 -1.19667158 -1.09778475 -1.16184934 -1.16445153 -1.1152839 -1.11352298
## 3 0.87033922 0.79508421 0.85775583 0.84637842 0.8357223 0.76088025
## 4 1.56058901 1.43297313 1.46948401 1.49626787 1.4654223 1.53504407
## promedio competitividad
## 1 -0.1045220 -0.07283521
## 2 -0.6902260 -1.19787635
## 3 0.6134411 0.83550054
## 4 0.8599769 1.63602476
cat("\nSSE total:\n")
##
## SSE total:
print(modelo_KMeans$tot.withinss)
## [1] 3434.418
cat("\nSSE por clúster:\n")
##
## SSE por clúster:
print(modelo_KMeans$withinss)
## [1] 1311.8313 1089.3458 755.2148 278.0262
Se manda llamar la función f_dispersion_variables_clusters() y se observan las dispersiones de pares de variables identificando los grupos formados.
Por cuestión práctica solo se muestran combinaciones de pares de las variables, entrenamiento, , fuerza, y promedio, que son tres seleccionadas aleatoriamente por el autor para no saturar los gráficos, luego otras tres variables también aleatorias seleccionadas por el autor, edad, velocidad y competitividad.
variables_graficos_1 <- c("entrenamiento", "fuerza", "promedio")
variables_graficos_2 <- c("edad", "velocidad", "competitividad")
f_dispersion_variables_clusters(
datos = datos_estandarizados,
variable_cluster = "cluster_kmeans",
variables = variables_graficos_1,
centroides = modelo_KMeans$centers,
titulo = "K-Means: dispersión por pares de variables",
ncol = 3
)
f_dispersion_variables_clusters(
datos = datos_estandarizados,
variable_cluster = "cluster_kmeans",
variables = variables_graficos_2,
centroides = modelo_KMeans$centers,
titulo = "K-Means: dispersión por pares de variables",
ncol = 3
)
Se manda llamar la función f_diagramas_cajas() y se observan los diagramas de cajas que ayudan a identificar de manera más amigable los grupos y se observan algunas incidencias:
f_diagramas_cajas(
datos = datos_estandarizados,
variable_cluster = "cluster_kmeans",
variables = variables_graficos_1,
titulo = "K-Means: comparación de variables por clúster",
ncol = 3
)
f_diagramas_cajas(
datos = datos_estandarizados,
variable_cluster = "cluster_kmeans",
variables = variables_graficos_2,
titulo = "K-Means: comparación de variables por clúster",
ncol = 3
)
Se construye el modelo K-Means con la función f_crear_KMeans() con los datos estandarizados.
modelo_KMedians <- f_crear_KMedians(
datos = datos_estandarizados,
variables = variables,
centers = 4,
nstart = 25,
max_iter = 100,
semilla = 2026,
estandarizar = FALSE
)
Se observan los clústeres y los centroides o medianas
# Clúster asignado a cada observación
modelo_KMedians$cluster
## [1] 1 4 4 3 1 3 2 1 3 3 3 1 3 4 3 1 4 4 3 3 3 1 1 3 1 3 3 4 4 3 4 3 3 3 3 3 3
## [38] 1 2 3 3 4 3 3 1 4 3 2 3 3 4 1 3 3 3 3 3 1 1 3 1 3 3 1 1 4 1 4 4 3 4 1 3 1
## [75] 4 3 3 4 4 1 3 1 3 3 2 1 3 4 3 3 1 2 3 1 3 1 4 3 4 3 3 1 4 4 3 1 1 3 1 3 3
## [112] 3 4 1 3 3 3 3 4 2 2 4 4 3 2 2 4 3 1 3 1 4 3 1 2 4 3 4 3 3 4 4 2 3 3 1 1 4
## [149] 1 1 4 1 4 3 1 4 1 1 1 3 3 1 3 4 3 1 3 2 1 3 1 4 1 1 2 4 4 4 3 3 3 4 4 1 3
## [186] 1 4 3 2 3 4 1 3 1 4 3 4 1 3 4 3 4 1 2 1 3 4 1 1 4 1 3 3 1 3 3 4 3 1 4 3 2
## [223] 4 2 2 4 3 3 3 4 4 4 4 1 1 4 3 2 3 3 4 3 2 3 4 3 2 3 1 1 4 3 1 3 4 2 1 1 4
## [260] 4 3 4 2 4 3 4 4 4 3 3 4 3 4 3 3 4 3 4 3 4 1 4 4 1 4 1 2 1 1 2 3 1 3 2 4 2
## [297] 1 1 4 3 4 1 4 4 4 1 3 3 3 4 3 1 4 3 3 2 3 2 3 3 4 3 2 4 4 3 3 1 4 2 1 2 3
## [334] 1 3 3 3 1 3 4 2 2 3 3 4 4 3 3 1 1 1 2 3 4 4 3 4 4 3 3 3 4 1 4 4 1 3 3 3 1
## [371] 2 3 4 1 1 4 1 3 1 4 3 2 1 1 1 4 3 1 1 4 4 3 2 3 4 3 4 3 4 1 3 4 2 3 2 4 1
## [408] 3 3 4 4 3 2 3 3 3 4 4 3 1 3 4 2 1 3 2 2 3 1 3 4 4 4 4 3 4 2 4 3 3 3 3 1 4
## [445] 4 2 1 4 3 4 4 1 3 1 2 4 4 4 1 2 3 3 3 1 1 4 1 4 4 3 4 1 3 4 2 4 3 4 1 4 4
## [482] 3 1 1 4 4 3 4 1 4 3 2 2 4 4 2 1 2 3 1 4 3 1 4 1 3 3 3 2 3 1 1 2 3 3 3 3 2
## [519] 3 3 3 3 2 4 4 3 4 4 1 3 4 2 3 4 1 3 4 3 1 1 4 3 3 1 3 1 3 4 3 1 3 4 3 1 4
## [556] 1 4 3 3 4 3 4 1 3 1 3 4 4 1 3 3 3 4 2 3 1 3 1 1 2 1 1 1 3 1 1 4 3 1 4 3 3
## [593] 3 4 3 3 1 3 4 4 1 1 2 1 3 3 3 4 3 4 1 4 3 2 4 4 4 2 2 4 2 1 3 2 1 3 1 3 3
## [630] 4 3 4 3 2 3 1 3 2 1 4 4 2 2 3 4 4 1 1 3 3 4 4 4 2 1 4 4 1 1 1 4 2 4 3 3 2
## [667] 1 3 3 1 4 4 2 3 3 3 1 3 1 3 1 4 3 3 4 2 2 3 4 4 4 3 3 1 3 1 2 4 3 1 2 4 1
## [704] 4 1 4 1 2 3 4 3 3 1 4 1 3 4 1 4 4 3 1 1 4 1 1 4 2 4 4 3 1 4 3 3 1 1 4 4 3
## [741] 1 3 3 3 1 3 1 2 2 1 4 3 4 1 3 1 4 1 3 1 3 3 3 2 1 3 4 2 4 1 2 4 4 1 1 3 4
## [778] 4 2 1 1 3 4 4 3 2 2 1 4 3 4 4 1 3 3 4 3 3 3 3 3 3 4 1 2 3 4 2 3 1 1 3 4 2
## [815] 4 3 4 4 1 3 4 4 1 2 4 1 4 1 3 2 3 2 3 3 3 4 4 4 2 3 1 3 3 3 2 1 4 4 4 3 3
## [852] 1 1 4 2 3 3 3 3 1 1 2 1 1 4 1 1 4 1 3 4 3 3 4 4 3 3 3 3 1 1 1 4 3 3 1 2 3
## [889] 3 1 1 3 3 4 4 4 4 1 3 4 1 4 4 4 2 4 1 2 1 1 4 1 1 3 1 1 1 1 3 3 3 4 3 3 4
## [926] 4 3 4 2 3 3 4 3 4 4 3 1 3 4 4 1 1 1 3 3 1 3 1 3 3 4 4 1 3 2 3 4 3 3 3 4 1
## [963] 3 3 3 3 3 3 3 3 3 3 4 3 3 4 3 4 3 1 3 3 4 3 3 3 4 4 2 4 3 4 3 4 3 4 1 3 4
## [1000] 4
# Medianas finales
modelo_KMedians$medianas_originales
# SAD total
modelo_KMedians$SAD_total
## [1] 7159.387
# SAD por clúster
modelo_KMedians$SAD_por_cluster
## 1 2 3 4
## 1338.4062 583.1641 2963.0405 2274.7762
# Número de iteraciones
modelo_KMedians$iteraciones
## [1] 1
datos_estandarizados$cluster_kmedians <- modelo_KMedians$cluster
Se manda llamar la función f_dispersion_variables_clusters() y se observan las dispersiones de pares de variables identificando los grupos formados.
f_dispersion_variables_clusters(
datos = datos_estandarizados,
variable_cluster = "cluster_kmedians",
variables = variables_graficos_1,
centroides = modelo_KMedians$medianas_originales,
titulo = "K-Medians: dispersión por pares de variables",
ncol = 2
)
f_dispersion_variables_clusters(
datos = datos_estandarizados,
variable_cluster = "cluster_kmedians",
variables = variables_graficos_2,
centroides = modelo_KMedians$medianas_originales,
titulo = "K-Medians: dispersión por pares de variables",
ncol = 2
)
Se manda llamar la función f_diagramas_cajas() y se observan los diagramas de cajas que ayudan a identificar de manera más amigable los grupos y se observan algunas incidencias:
f_diagramas_cajas(
datos = datos_estandarizados,
variable_cluster = "cluster_kmeans",
variables = variables_graficos_1,
titulo = "K-Medians: comparación de variables por clúster",
ncol = 3
)
f_diagramas_cajas(
datos = datos_estandarizados,
variable_cluster = "cluster_kmeans",
variables = variables_graficos_2,
titulo = "K-Medians: comparación de variables por clúster",
ncol = 3
)
Este caso de estudio ofrece una implementación de los modelos de clustering K-Means y K-Medians con un conjunto de datos de mil registros relacionado con aspectos deportivos de estudiantes de nivel superior.
Se describió el contexto de los datos; se plasmó el objetivo del caso de estudio; se extrajeron los datos estadísticos de las variables; antes de implementar los modelos de clustering, se modificaron los datos atípicos y se identificaron correlaciones de las cuales no hubo incidencia fuerte para modificar de acuerdo a la correlación entre variables; se estandarizaron todos los datos de tal forma que los modelos usaron los datos estandarizados.
Se establecieron cuatro grupos a extraer con los modelos de clustering.
Los resultados de los modelos K-Means y K-Medians son similares en estructura ambos concuerdan en que valores altos en las variables reflejan un grupo de por así llamarlo de élite o alto rendimiento, valores buenos y medianos reflejan deportistas buenos y de medio rendimiento y valores bajos en las variables definen a un grupo de no deportistas.
El caso de estudio cumple con el objetivo establecido y tiene la utilidad de que las funciones y estructura de caso aquí presentado pueden servir de guía para los estudiantes y lectores que deseen recrear sus propios modelos de clustering con estos u otros datos.
En cuanto a una evaluación de los dos modelos, la pregunta es ¿cuál modelo es mejor?
La respuesta correcta no es comparable el estadístico SSE de K-Means contra SAD de K-Medians, porque son criterios distintos. K-Means minimiza distancias cuadráticas con distancia euclidiana; K-Medians minimiza distancias absolutas con distancia Manhattan.
De acuerdo a IAG OpenAI, 2026, para este caso con datos de estudiantes deportistas, K-Means parece ser el modelo más adecuado si el objetivo es obtener grupos compactos y visualmente bien centrados. Por otra parte, K-Medians es útil como alternativa robusta, pero debe evaluarse con distancia Manhattan y preferentemente con datos estandarizados.
K-Means es ligeramente más recomendable para este caso de estudio, porque los grupos parecen estar bien separados, los centroides representan adecuadamente el centro visual de cada grupo y los datos no muestran una estructura claramente dominada por valores atípicos. Sin embargo, K-Medians estandarizado también produce una solución coherente y puede presentarse como una alternativa más robusta cuando se desea reducir la influencia de valores extremos.
Finamente, para comparar y evaluar modelos de clustering, es recomendable utilizar métricas internas comunes, tales como el coeficiente de Silhouette, el índice de Calinski-Harabasz y el índice de Davies-Bouldin. Estas métricas evalúan la cohesión interna de los grupos y la separación entre clústeres, independientemente del algoritmo utilizado para construirlos. De esta manera, es posible comparar K-Means, K-Medians, y otros modelos bajo criterios de evaluación homogéneos.
Por el momento estas métricas de comparación se escapan de este caso de estudio y más adelante serán descritas. .