2013-06-02 19 views
14

Miałem zamieszanie dotyczące tego modułu (scipy.cluster.hierarchy) ... i nadal mają niektóre!Jak uzyskać subtrees of dendrogram przez scipy.cluster.hierarchy

Na przykład mamy następujący dendrogram:

hierarchical clustering

Moje pytanie brzmi: w jaki sposób można wyodrębnić kolorowych poddrzewa (każdy z nich reprezentuje klaster) w ładnej formie, powiedzmy Format SIF? Teraz kod, aby uzyskać wykres powyżej:

import scipy 
import scipy.cluster.hierarchy as sch 
import matplotlib.pylab as plt 

scipy.randn(100,2) 

d = sch.distance.pdist(X) 

Z= sch.linkage(d,method='complete') 

P =sch.dendrogram(Z) 

plt.savefig('plot_dendrogram.png') 

T = sch.fcluster(Z, 0.5*d.max(), 'distance') 
#array([4, 5, 3, 2, 2, 3, 5, 2, 2, 5, 2, 2, 2, 3, 2, 3, 2, 5, 4, 5, 2, 5, 2, 
#  3, 3, 3, 1, 3, 4, 2, 2, 4, 2, 4, 3, 3, 2, 5, 5, 5, 3, 2, 2, 2, 5, 4, 
#  2, 4, 2, 2, 5, 5, 1, 2, 3, 2, 2, 5, 4, 2, 5, 4, 3, 5, 4, 4, 2, 2, 2, 
#  4, 2, 5, 2, 2, 3, 3, 2, 4, 5, 3, 4, 4, 2, 1, 5, 4, 2, 2, 5, 5, 2, 2, 
#  5, 5, 5, 4, 3, 3, 2, 4], dtype=int32) 

sch.leaders(Z,T) 
# (array([190, 191, 182, 193, 194], dtype=int32), 
# array([2, 3, 1, 4,5],dtype=int32)) 

Więc teraz, wyjście fcluster() daje grupowanie węzłów (według ich identyfikatorów) i leaders() opisane here ma powrócić 2 tablice:

  • pierwsza zawiera węzły lider klastrów generowanych przez z, tutaj widzimy, mamy 5 klastrów, jak również działki

  • a drugi z identyfikatorów z te klastry:

Więc jeśli ten lider() zwróci resp. L i M: L[2]=182 i M[2]=1, wówczas klaster 1 jest prowadzony przez identyfikator węzła 182, który nie istnieje w zestawie obserwacji X, dokumentacja mówi "... wtedy odpowiada klastrze nie singleton". Ale nie mogę tego uzyskać ...

Przekonwertowałem również Z na drzewo przez sch.to_tree(Z), które zwróci łatwy w użyciu obiekt drzewa, który chcę wizualizować, ale które narzędzie powinienem użyć jako platforma graficzna, która manipuluje takimi obiektami drzewa jako danymi wejściowymi?

Odpowiedz

19

Odpowiadając na część pytania dotyczące manipulacji drzewa ...

Jak wyjaśniono w aother answer można odczytać współrzędne oddziałach czytanie icoord i dcoord z obiektu drzewa. Dla każdego oddziału skoordynowane są podane od lewej do prawej.

Jeśli chcesz ręcznie wykreślić drzewa można użyć coś takiego:

def plot_tree(P, pos=None): 
    icoord = scipy.array(P['icoord']) 
    dcoord = scipy.array(P['dcoord']) 
    color_list = scipy.array(P['color_list']) 
    xmin, xmax = icoord.min(), icoord.max() 
    ymin, ymax = dcoord.min(), dcoord.max() 
    if pos: 
     icoord = icoord[pos] 
     dcoord = dcoord[pos] 
     color_list = color_list[pos] 
    for xs, ys, color in zip(icoord, dcoord, color_list): 
     plt.plot(xs, ys, color) 
    plt.xlim(xmin-10, xmax + 0.1*abs(xmax)) 
    plt.ylim(ymin, ymax + 0.1*abs(ymax)) 
    plt.show() 

Jeżeli w kodzie, plot_tree(P) daje:

enter image description here

Funkcja umożliwia wybranie tylko niektóre oddziały:

plot_tree(P, range(10)) 

enter image description here

Teraz musisz wiedzieć, które gałęzie do spisku.Może wyjście fcluster() jest trochę niejasne i inny sposób, aby dowiedzieć się, jakie gałęzie działki w oparciu o minimalną i maksymalną tolerancją na odległość będzie za pomocą wyjścia linkage() bezpośrednio (Z w przypadku, gdy OP):

dmin = 0.2 
dmax = 0.3 
pos = scipy.all((Z[:,2] >= dmin, Z[:,2] <= dmax), axis=0).nonzero() 
plot_tree(P, pos) 

Zalecane referencje:

+2

Ten POUFNY er pomógł mi dostać się tam, gdzie mogłem wykreślić poddrzewa z dendrogramu z obserwacjami znalezionymi w danej odległości fenetycznej (PD). Nie znalazłem w tym celu metod fcluster lub fclusterdata. Użyłem sch.to_tree (linkage) .pre_order(), a następnie przetestowałem kolejno sąsiednie elementy na tej liście, aby znaleźć się w PD, odwołując się do macierzy odległości pdist (patrz http://stackoverflow.com/a/17870926/1876324), następnie ponownie obliczyć odległość, powiązanie i dendrogram dla każdej grupy, którą chciałem wydrukować. Na przykład PD o wartości 4 zgrupowałoby dane OP w pożądanych 3 poddrzewach. –