Analítica de Personas · Semestre otoño 2026 · Semana 14 · Prof. René Gempp
El Apunte 31 cubrió el aprendizaje supervisado: había una Y conocida —la rotación— y el objetivo era predecirla. Ahora le quitamos la Y al problema. El CEO no pregunta "¿quién va a rotar?" sino algo distinto: "¿qué tipos de empleado tenemos? Descúbranlos sin que yo les diga cuáles son ni cuántos hay."
Eso es aprendizaje no supervisado: no hay variable respuesta, no hay "respuesta correcta" contra la cual corregirse. El objetivo es descubrir estructura que está latente en los datos. La técnica que usaremos es el análisis de conglomerados (cluster analysis): agrupar empleados de modo que los de un mismo grupo se parezcan mucho entre sí y se diferencien de los de otros grupos.
La pregunta cambia de raíz: ya no es "¿qué predice Y?" sino "¿quién se parece a quién?".
Si hiciste el EFA de la Clase 6, ya entiendes el clustering mejor de lo que crees. Toda matriz de datos tiene dos márgenes: las columnas (variables) y las filas (casos).
| Técnica | ¿Qué reduce? | ¿Qué descubre? |
|---|---|---|
| Análisis factorial (EFA) | Las columnas (variables) | Factores latentes que explican la covarianza entre variables |
| Clustering | Las filas (casos) | Grupos latentes que explican la similitud entre personas |
Todo el clustering descansa sobre una medida de distancia entre personas. La más común para variables continuas es la distancia euclidiana:
De aquí surge la decisión más importante y más olvidada: la estandarización. Mira las escalas de InnovaCo: el ingreso está en millones (≈ 1.600.000) y la satisfacción en una escala de 1 a 5. Si calculas la distancia euclidiana sin estandarizar, el ingreso aplasta todo lo demás: una diferencia de \$200.000 pesa 200.000 unidades, mientras que toda la escala de satisfacción pesa, como mucho, 4 unidades. La satisfacción se vuelve irrelevante por su escala, no por su importancia.
# Variables de perfil del empleado
seg_vars <- empleados |>
select(edad, antiguedad_anios, ingreso_mensual,
satisfaccion_laboral, evaluacion_desempeno, horas_capacitacion)
# CRÍTICO: estandarizar a puntajes z (media 0, desviación 1)
seg_z <- scale(seg_vars)
scale() es el error más común y el más caro en segmentación.
Esta es la advertencia conceptual central del apunte. Un algoritmo de clustering siempre devuelve conglomerados, incluso si los datos no tienen ninguna estructura de grupos —incluso en una nube uniforme y aleatoria. El algoritmo no pregunta "¿hay grupos?"; pregunta "si tuviera que partir esto en k grupos, ¿cuál es la mejor partición?".
Por lo tanto, encontrar conglomerados no prueba que existan grupos "reales". La validez de una solución se evalúa por su estabilidad, su interpretabilidad y, sobre todo, por validación externa (sección 9). La tendencia a agrupar puede chequearse antes con el estadístico de Hopkins:
set.seed(2026)
get_clust_tendency(seg_z, n = 50)$hopkins_stat
# > 0.5 sugiere alguna estructura agrupable
k-means (Hartigan & Wong, 1979) parte el conjunto en k grupos minimizando la dispersión interna total (la suma de cuadrados intra-conglomerado). El algoritmo:
set.seed(2026)
km <- kmeans(seg_z, centers = 4, nstart = 25)
km$size # tamaño de cada conglomerado
km$tot.withinss # dispersión intra-conglomerado total
| Característica | Implicancia práctica |
|---|---|
| Requiere fijar k de antemano | Hay que elegirlo con diagnósticos (sección 6) |
| Sensible a la inicialización | Usar nstart = 25 o más: corre muchas veces y se queda con la mejor |
| Sensible a la escala | Estandarizar siempre (sección 3) |
| Asume grupos esféricos y de tamaño similar | Falla con grupos alargados o de densidades muy distintas |
| Solo variables continuas | Para categóricas, usar Gower + PAM (sección 12) |
No hay una respuesta única a "¿cuántos grupos hay?". Hay diagnósticos que sugieren:
library(factoextra)
fviz_nbclust(seg_z, kmeans, method = "wss") # codo
fviz_nbclust(seg_z, kmeans, method = "silhouette") # silueta
Con seis variables no podemos graficar en seis dimensiones. fviz_cluster() proyecta los grupos sobre las dos primeras componentes principales (un resumen bidimensional que conserva la mayor varianza posible):
fviz_cluster(km, data = seg_z, geom = "point",
ellipse.type = "norm",
palette = c(col_teal, col_terracotta, col_gold, col_purple),
main = "Segmentos de empleados (k-means, k = 4)")
Las elipses muestran la dispersión de cada grupo. Si se superponen mucho, es otra señal de que la separación es débil —coherente con una silueta modesta.
El algoritmo entrega una etiqueta numérica por persona (1, 2, 3, 4). Ese número no significa nada por sí solo. El valor lo agregas tú al perfilar: calcular, para cada grupo, el promedio de las variables en su escala original (no la estandarizada) y construir un retrato.
perfil <- empleados |>
mutate(segmento = factor(km$cluster)) |>
group_by(segmento) |>
summarise(
n = n(),
edad = mean(edad),
antiguedad = mean(antiguedad_anios),
ingreso = mean(ingreso_mensual),
satisfaccion = mean(satisfaccion_laboral),
desempeno = mean(evaluacion_desempeno),
capacitacion = mean(horas_capacitacion)
)
A partir de la tabla de perfiles, los segmentos de InnovaCo que tienden a emerger se pueden nombrar así (los nombres son tu interpretación, no salida del algoritmo):
¿Cómo sabemos que los segmentos son útiles y no artefactos del algoritmo? Cruzándolos con una variable que no se usó para formarlos. Formamos los grupos con edad, antigüedad, ingreso, satisfacción, desempeño y capacitación. La rotación quedó fuera. Si los segmentos difieren marcadamente en su tasa de rotación, capturan algo real.
empleados |>
mutate(segmento = factor(km$cluster)) |>
count(segmento, rotacion) |>
group_by(segmento) |>
mutate(prop = n / sum(n)) |>
filter(rotacion == "Sí")
El clustering jerárquico aglomerativo ofrece una lógica distinta: empieza con cada persona como su propio grupo y, en cada paso, fusiona los dos grupos más cercanos, hasta dejar todo en uno solo. El resultado es un dendrograma: un árbol que muestra el orden y la distancia de las fusiones.
Ventajas frente a k-means: no requiere fijar k de antemano (cortas el dendrograma a la altura que quieras) y es determinista (no depende de inicialización aleatoria). La decisión clave es el método de enlace: cómo se mide la distancia entre grupos. El enlace de Ward (ward.D2) produce grupos compactos y de tamaño similar, y es el más usado en segmentación de personas.
d <- dist(seg_z, method = "euclidean")
hc <- hclust(d, method = "ward.D2")
fviz_dend(hc, k = 4, cex = 0.4) # dendrograma coloreado
grupos_hc <- cutree(hc, k = 4) # cortar en 4 grupos
Una solución de clustering es más creíble si distintos métodos coinciden. Cruzamos las etiquetas de k-means con las del jerárquico:
table(kmeans = km$cluster, jerarquico = grupos_hc)
Si la tabla muestra una correspondencia clara (cada grupo de un método cae mayormente en un grupo del otro), la solución es estable. Si las etiquetas se mezclan, conviene ser cauto: la estructura es débil y la segmentación, frágil.
El k-means solo admite variables continuas (usa medias y distancia euclidiana). ¿Y si quieres segmentar incluyendo el departamento o el género? Para datos mixtos (continuos + categóricos) se usa la distancia de Gower (Gower, 1971), que combina una métrica apropiada por tipo de variable, junto con PAM (Partitioning Around Medoids; Kaufman & Rousseeuw, 1990) —una variante de k-means que opera sobre una matriz de distancias.
library(cluster)
seg_mix <- empleados |>
select(edad, antiguedad_anios, ingreso_mensual,
satisfaccion_laboral, departamento, genero) |>
mutate(across(c(departamento, genero), as.factor))
d_gower <- daisy(seg_mix, metric = "gower")
pam_fit <- pam(d_gower, k = 4)
satisfaccion_laboral y evaluacion_desempeno (Likert de 1 a 5) como continuas. Como psicómetras sabemos que la distancia entre "1" y "2" no es necesariamente igual a la de "4" a "5". Es una simplificación pedagógica que declaramos; un proyecto riguroso usaría Gower o un modelo para datos ordinales. Lo mismo con ingreso_mensual, fuertemente sesgado a la derecha: convendría transformarlo (log) para que un puñado de gerentes muy bien pagados no domine la solución.
mclust, Scrucca, Fop, Murphy & Raftery, 2016). El LPA entrega lo que el k-means no: asignación probabilística a los perfiles (cada persona tiene una probabilidad de pertenecer a cada grupo), criterios de información (BIC, AIC) para elegir el número de perfiles, y pruebas formales de ajuste. Para quien viene del mundo SEM, el LPA es el marco natural y se ha vuelto estándar en la investigación organizacional y vocacional (Spurk, Hirschi, Wang, Valero & Kauffeld, 2020). En R: tidyLPA. Otras fronteras: el clustering por densidad (DBSCAN), que detecta grupos de forma arbitraria y aísla outliers, y la reducción no lineal (UMAP, t-SNE) para visualizar estructura de alta dimensión.
La postura del curso, una vez más: enseñar bien lo estándar, declarar la frontera y dar las referencias. Sabes ejecutar y validar un k-means; sabes que existe el LPA y por qué es más principista. Eso es suficiente para ser un consumidor crítico y un practicante competente.
El clustering descubre, sin etiqueta, la estructura latente entre las personas, como el EFA la descubrió entre las variables. Sus claves: estandarizar siempre, recordar que el algoritmo siempre devuelve grupos (y que eso no prueba que existan), elegir k con codo y silueta sin tratarlos como oráculos, y —sobre todo— perfilar, nombrar y validar externamente. El mensaje de fondo que cierra la clase: los algoritmos no descubren verdades, proponen estructuras; el analista las valida y les da sentido.
scale(), dist(), get_clust_tendency(), kmeans(), fviz_nbclust(), fviz_cluster(), hclust(), cutree(), fviz_dend(), cluster::daisy(metric = "gower"), cluster::pam().
Everitt, B. S., Landau, S., Leese, M., & Stahl, D. (2011). Cluster analysis (5.ª ed.). Wiley.
Gower, J. C. (1971). A general coefficient of similarity and some of its properties. Biometrics, 27(4), 857–871. https://doi.org/10.2307/2528823
Hartigan, J. A., & Wong, M. A. (1979). Algorithm AS 136: A k-means clustering algorithm. Journal of the Royal Statistical Society. Series C, 28(1), 100–108. https://doi.org/10.2307/2346830
James, G., Witten, D., Hastie, T., & Tibshirani, R. (2021). An introduction to statistical learning with applications in R (2.ª ed.). Springer. https://www.statlearning.com
Kaufman, L., & Rousseeuw, P. J. (1990). Finding groups in data: An introduction to cluster analysis. Wiley.
Rousseeuw, P. J. (1987). Silhouettes: A graphical aid to the interpretation and validation of cluster analysis. Journal of Computational and Applied Mathematics, 20, 53–65. https://doi.org/10.1016/0377-0427(87)90125-7
Scrucca, L., Fop, M., Murphy, T. B., & Raftery, A. E. (2016). mclust 5: Clustering, classification and density estimation using Gaussian finite mixture models. The R Journal, 8(1), 289–317.
Spurk, D., Hirschi, A., Wang, M., Valero, D., & Kauffeld, S. (2020). Latent profile analysis: A review and "how to" guide of its application within vocational behavior research. Journal of Vocational Behavior, 120, 103445. https://doi.org/10.1016/j.jvb.2020.103445
Tibshirani, R., Walther, G., & Hastie, T. (2001). Estimating the number of clusters in a data set via the gap statistic. Journal of the Royal Statistical Society. Series B, 63(2), 411–423. https://doi.org/10.1111/1467-9868.00293
Vermunt, J. K., & Magidson, J. (2002). Latent class cluster analysis. En J. A. Hagenaars & A. L. McCutcheon (Eds.), Applied latent class analysis (pp. 89–106). Cambridge University Press.