python - how - numpy clustering
Cómo obtener una agrupación plana correspondiente a los grupos de colores en el dendrograma creado por scipy (4)
Creo que estás en el camino correcto. Intentemos esto:
import scipy
import scipy.cluster.hierarchy as sch
X = scipy.randn(100, 2) # 100 2-dimensional observations
d = sch.distance.pdist(X) # vector of (100 choose 2) pairwise distances
L = sch.linkage(d, method=''complete'')
ind = sch.fcluster(L, 0.5*d.max(), ''distance'')
ind
le dará índices de grupo para cada una de las 100 observaciones de entrada. ind
depende de qué method
linkage
en el linkage
. Prueba el method=single
, complete
y average
. Luego note cómo difiere ind
.
Ejemplo:
In [59]: L = sch.linkage(d, method=''complete'')
In [60]: sch.fcluster(L, 0.5*d.max(), ''distance'')
Out[60]:
array([5, 4, 2, 2, 5, 5, 1, 5, 5, 2, 5, 2, 5, 5, 1, 1, 5, 5, 4, 2, 5, 2, 5,
2, 5, 3, 5, 3, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 4, 1, 4, 5, 2, 1, 4,
2, 4, 2, 2, 5, 5, 5, 2, 5, 5, 3, 5, 5, 4, 5, 4, 5, 3, 5, 3, 5, 5, 5,
2, 3, 5, 5, 4, 5, 5, 2, 2, 5, 2, 2, 4, 1, 2, 1, 5, 2, 5, 5, 5, 1, 5,
4, 2, 4, 5, 2, 4, 4, 2])
In [61]: L = sch.linkage(d, method=''single'')
In [62]: sch.fcluster(L, 0.5*d.max(), ''distance'')
Out[62]:
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1])
scipy.cluster.hierarchy
seguro es confuso. En tu enlace, ¡ni siquiera reconozco mi propio código!
Usando el código publicado here , creé una buena agrupación jerárquica:
Digamos que el dendrograma de la izquierda se creó haciendo algo como
Y = sch.linkage(D, method=''average'') # D is a distance matrix
cutoff = 0.5*max(Y[:,2])
Z = sch.dendrogram(Y, orientation=''right'', color_threshold=cutoff)
Ahora, ¿cómo obtengo los índices de los miembros de cada uno de los grupos de colores? Para simplificar esta situación, ignore la agrupación en la parte superior y céntrese solo en el dendrograma a la izquierda de la matriz.
Esta información debe almacenarse en la variable almacenada del dendrograma Z
Hay una función que debería hacer exactamente lo que quiero que se llame fcluster
(consulte la documentación here ). Sin embargo, no puedo ver dónde puedo dar a fcluster el mismo cutoff
que especifiqué en la creación del dendrograma. Parece que la variable de umbral en fcluster
, t
tiene que ser en términos de varias medidas oscuras ( inconsistent
, distance
, maxclust
, monocrit
). ¿Algunas ideas?
Escribí algún código para descondensar la matriz de enlace. Devuelve un diccionario que contiene los índices de labels
que se agrupan por cada paso de aglomeración. Solo lo he probado con los resultados de los clústeres de vinculación complete
. Las claves del dict comienzan en len(labels)+1
porque inicialmente, cada etiqueta se trata como su propio grupo. Esto puede responder a su pregunta.
import pandas as pd
import numpy as np
from scipy.cluster.hierarchy import linkage
np.random.seed(123)
labels = [''ID_0'',''ID_1'',''ID_2'',''ID_3'',''ID_4'']
X = np.corrcoef(np.random.random_sample([5,3])*10)
row_clusters = linkage(x_corr, method=''complete'')
def extract_levels(row_clusters, labels):
clusters = {}
for row in xrange(row_clusters.shape[0]):
cluster_n = row + len(labels)
# which clusters / labels are present in this row
glob1, glob2 = row_clusters[row, 0], row_clusters[row, 1]
# if this is a cluster, pull the cluster
this_clust = []
for glob in [glob1, glob2]:
if glob > (len(labels)-1):
this_clust += clusters[glob]
# if it isn''t, add the label to this cluster
else:
this_clust.append(glob)
clusters[cluster_n] = this_clust
return clusters
Devoluciones:
{5: [0.0, 2.0],
6: [3.0, 4.0],
7: [1.0, 0.0, 2.0],
8: [3.0, 4.0, 1.0, 0.0, 2.0]}
Sé que esto es muy tarde para el juego, pero hice un objeto de trazado basado en el código del post here . Está registrado en pip, así que para instalarlo solo tienes que llamar
pip install pydendroheatmap
Echa un vistazo a la página de github del proyecto aquí: https://github.com/themantalope/pydendroheatmap
También puedes probar cut_tree
, tiene un parámetro de altura que debería darte lo que quieres para la ultrametría.