W3docs

Agrupamiento Jerárquico

Aprende agrupamiento jerárquico en Python con scikit-learn y SciPy: métodos de enlace, dendrogramas y cuándo elegirlo sobre K-Means.

El agrupamiento jerárquico es un algoritmo de aprendizaje automático no supervisado que agrupa puntos de datos en un árbol de clústeres anidados, sin necesidad de especificar el número de clústeres de antemano. Esta página explica cómo funciona el algoritmo, la diferencia entre los enfoques aglomerativo y divisivo, cómo elegir un método de enlace, y cómo implementar y visualizar el agrupamiento jerárquico en Python usando scikit-learn y SciPy.

¿Qué es el Agrupamiento Jerárquico?

El agrupamiento jerárquico construye una jerarquía de clústeres fusionando o dividiendo iterativamente grupos de puntos de datos según una medida de distancia (o similitud). El resultado se representa como un dendrograma — un diagrama en forma de árbol donde el eje y muestra la distancia a la que se fusionan los clústeres y las hojas representan puntos de datos individuales.

A diferencia de K-Means, el agrupamiento jerárquico no requiere elegir el número de clústeres antes de ejecutar el algoritmo. Se ejecuta el algoritmo una vez y luego se "corta" el dendrograma en un umbral de distancia elegido para producir cualquier número de clústeres.

Cuándo usar el agrupamiento jerárquico

Usa el agrupamiento jerárquico cuando:

  • No conoces el número de clústeres de antemano y deseas explorar varias opciones desde una sola ejecución.
  • Tu conjunto de datos es de tamaño pequeño a mediano (miles de filas, no millones) — el costo de memoria O(n²) del algoritmo lo hace poco práctico para conjuntos de datos muy grandes.
  • Necesitas relaciones de clústeres interpretables (el dendrograma revela claramente el historial de fusiones).
  • Tus clústeres pueden no ser esféricos — los métodos jerárquicos con enlace completo o promedio manejan formas no globulares mejor que K-Means.

Agrupamiento Aglomerativo vs. Divisivo

Existen dos estrategias principales:

EstrategiaDirecciónCómo funciona
Aglomerativo (ascendente)Comienza con cada punto como su propio clúster y luego fusiona repetidamente los dos clústeres más cercanos.El más común; usado por AgglomerativeClustering de scikit-learn y linkage de SciPy.
Divisivo (descendente)Comienza con todos los puntos en un clúster y luego divide recursivamente el clúster más grande.Raramente usado en la práctica; computacionalmente costoso.

Esta página se centra en el agrupamiento aglomerativo, que es lo que la mayoría de los profesionales entienden cuando dicen "agrupamiento jerárquico".

Cómo Funciona el Algoritmo

El agrupamiento aglomerativo sigue estos pasos:

  1. Trata cada uno de los n puntos de datos como su propio clúster (n clústeres en total).
  2. Calcula la matriz de distancias — las distancias por pares entre todos los clústeres.
  3. Fusiona los dos clústeres con la distancia más pequeña en un nuevo clúster.
  4. Actualiza la matriz de distancias para reflejar el nuevo clúster.
  5. Repite los pasos 3–4 hasta que solo quede un clúster.

La salida final es un dendrograma que codifica todos los n-1 pasos de fusión.

Métodos de Enlace

El método de enlace controla cómo se calcula la distancia entre dos clústeres en cada paso de fusión. La elección afecta significativamente la forma y la calidad de los clústeres.

MétodoDistancia entre clústeres A y BIdeal para
WardIncremento en la varianza total intra-clúster después de fusionarClústeres compactos de tamaño aproximadamente igual (opción predeterminada)
CompleteDistancia máxima entre cualquier punto de A y cualquier punto de BClústeres compactos; evita el encadenamiento
AverageDistancia media entre todos los pares (uno de A, uno de B)Equilibrio entre enlace simple y completo
SingleDistancia mínima entre cualquier punto de A y cualquier punto de BDetección de clústeres alargados o de forma irregular; propenso al "encadenamiento"

El enlace Ward es el punto de partida más utilizado. Si tus clústeres son alargados o no convexos, prueba el enlace average o single.

Escalado de Características Antes del Agrupamiento

Dado que el agrupamiento jerárquico depende de cálculos de distancia, las características con rangos numéricos grandes dominan la matriz de distancias y sesgan los resultados. Siempre escala tus características primero.

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

StandardScaler centra cada característica a media 0 y varianza unitaria. Consulta el capítulo de Escala para conocer alternativas como MinMaxScaler y RobustScaler.

Implementar Agrupamiento Jerárquico con scikit-learn

La clase AgglomerativeClustering en scikit-learn ajusta el modelo y asigna etiquetas de clúster en un solo paso. No produce un dendrograma — usa SciPy (mostrado en la siguiente sección) para eso.

Paso 1 — Generar y escalar datos

from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler

# 150 points in 3 natural clusters
X, y_true = make_blobs(n_samples=150, centers=3, cluster_std=0.6, random_state=42)

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

make_blobs crea un conjunto de datos sintético reproducible, por lo que este ejemplo se ejecuta sin ningún archivo CSV.

Paso 2 — Ajustar el agrupamiento aglomerativo

from sklearn.cluster import AgglomerativeClustering

hc = AgglomerativeClustering(n_clusters=3, linkage='ward')
labels = hc.fit_predict(X_scaled)

print(labels[:10])
# e.g. [2 2 0 1 0 1 2 2 0 1]

fit_predict ajusta el modelo y devuelve la etiqueta de clúster (0, 1 o 2) para cada punto de datos en una sola llamada.

Paso 3 — Visualizar los clústeres

import matplotlib.pyplot as plt

colors = ['red', 'blue', 'green']
for cluster_id in range(3):
    mask = labels == cluster_id
    plt.scatter(X_scaled[mask, 0], X_scaled[mask, 1],
                s=60, label=f'Cluster {cluster_id + 1}')

plt.title('Agglomerative Clustering (Ward linkage, k=3)')
plt.xlabel('Feature 1 (scaled)')
plt.ylabel('Feature 2 (scaled)')
plt.legend()
plt.tight_layout()
plt.show()

Dendrogramas con SciPy

El dendrograma es la salida más distintiva del agrupamiento jerárquico. Permite elegir visualmente el número de clústeres cortando el árbol a diferentes alturas. El módulo scipy.cluster.hierarchy de SciPy proporciona tanto linkage (para construir el árbol) como dendrogram (para graficarlo).

Construir y graficar un dendrograma

from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt

# Use a smaller dataset so the dendrogram is readable
X, _ = make_blobs(n_samples=30, centers=3, cluster_std=0.6, random_state=42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# Build the linkage matrix
Z = linkage(X_scaled, method='ward')

# Plot
plt.figure(figsize=(12, 5))
dendrogram(Z, leaf_rotation=90, leaf_font_size=8)
plt.title('Dendrogram (Ward linkage)')
plt.xlabel('Sample index')
plt.ylabel('Merge distance')
plt.tight_layout()
plt.show()

Cómo leer el dendrograma

  • Las hojas (parte inferior) representan puntos de datos individuales.
  • Las líneas horizontales representan fusiones. La altura de una línea es igual a la distancia entre los dos clústeres que se fusionan.
  • Cortar el árbol a una altura determinada proporciona el número de clústeres por debajo de ese corte.

Para elegir k, busca la línea vertical más alta que no esté cruzada por una línea horizontal — esa brecha sugiere el número más natural de clústeres.

Cortar el dendrograma para asignar etiquetas

Después de construir la matriz de enlace Z, usa fcluster para cortar el árbol en el número deseado de clústeres:

from scipy.cluster.hierarchy import linkage, fcluster
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
import numpy as np

X, _ = make_blobs(n_samples=150, centers=3, cluster_std=0.6, random_state=42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

Z = linkage(X_scaled, method='ward')

# Cut the tree to get exactly 3 clusters
labels = fcluster(Z, t=3, criterion='maxclust')

print('Unique cluster IDs:', np.unique(labels))   # [1 2 3]  (1-indexed)
print('Sizes:', np.bincount(labels[labels > 0]))   # [50 50 50]

Ten en cuenta que las etiquetas de fcluster están indexadas desde 1 (comienzan en 1), a diferencia de las etiquetas indexadas desde 0 de scikit-learn.

Comparar Métodos de Enlace

El método de enlace cambia significativamente las formas y tamaños de los clústeres. Así se pueden comparar los cuatro métodos en el mismo conjunto de datos:

from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import numpy as np

X, _ = make_blobs(n_samples=150, centers=3, cluster_std=0.6, random_state=42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

methods = ['ward', 'complete', 'average', 'single']
fig, axes = plt.subplots(1, 4, figsize=(16, 4))

for ax, method in zip(axes, methods):
    hc = AgglomerativeClustering(n_clusters=3, linkage=method)
    labels = hc.fit_predict(X_scaled)
    ax.scatter(X_scaled[:, 0], X_scaled[:, 1], c=labels, cmap='Set1', s=30)
    ax.set_title(f'{method.capitalize()} linkage')
    ax.set_xticks([])
    ax.set_yticks([])

plt.suptitle('Linkage method comparison (k=3)', y=1.02)
plt.tight_layout()
plt.show()

Agrupamiento Jerárquico vs K-Means

CaracterísticaAgrupamiento jerárquicoK-Means
Número de clústeresSe elige después de ejecutar (inspeccionar el dendrograma)Debe especificarse antes de ejecutar
EscalabilidadEspacio O(n²) — tiene dificultades por encima de ~10 000 filasO(n·k·i) — escala a millones
DeterminismoCompletamente deterministaDepende de la inicialización aleatoria
Formas de clústeresFlexible (especialmente con enlace single/average)Asume clústeres esféricos
InterpretabilidadEl dendrograma muestra el historial completo de fusionesLos centroides son fácilmente interpretables

Usa el agrupamiento jerárquico para el análisis exploratorio en conjuntos de datos más pequeños; cambia a K-Means (o DBSCAN) cuando tengas millones de filas o ya conozcas el número de clústeres.

Errores Comunes

Olvidar escalar las características. Sin escalado de características, una característica medida en miles (por ejemplo, ingresos) domina a una medida en dígitos simples (por ejemplo, calificación de edad), produciendo clústeres engañosos.

Usar enlace Ward con distancias no euclidianas. El enlace Ward solo es válido con distancia euclidiana. Para otras métricas de distancia (por ejemplo, coseno, Manhattan), usa enlace completo o promedio y pasa metric= explícitamente.

Interpretar dendrogramas en conjuntos de datos muy grandes. Un dendrograma con 10 000 hojas es ilegible. Usa p= y truncate_mode='lastp' en dendrogram() de SciPy para mostrar solo las últimas p fusiones.

Tratar los IDs de clúster como estables. Los IDs de clúster (0, 1, 2) son etiquetas arbitrarias. Al comparar dos ejecuciones, empareja los clústeres por contenido, no por número.

Conclusión

El agrupamiento jerárquico es un algoritmo flexible e interpretable que no requiere elegir k de antemano. Se construye el dendrograma completo una vez y luego se corta en cualquier nivel. El enlace Ward con preprocesamiento StandardScaler es el predeterminado más seguro. Para conjuntos de datos muy grandes, prefiere K-Means por rendimiento.

Capítulos relacionados:

  • Scale — por qué y cómo estandarizar características antes del agrupamiento
  • K-Means — la alternativa de agrupamiento plano para conjuntos de datos grandes
  • SciPy Tutorial — más sobre la biblioteca de computación científica SciPy
  • Scatter Plot — visualización de datos multidimensionales con Matplotlib
Was this page helpful?