Как получить плоскую кластеризацию, соответствующую цветным кластерам в дендрограмме, созданной scipy - программирование
Подтвердить что ты не робот

Как получить плоскую кластеризацию, соответствующую цветным кластерам в дендрограмме, созданной scipy

Используя опубликованный код здесь, я создал хорошую иерархическую кластеризацию:

scipy dendrogram

Скажем, что дендрограмма слева была создана, сделав что-то вроде

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)

Теперь как мне получить индексы членов каждого из цветных кластеров?. Чтобы упростить эту ситуацию, проигнорируйте кластеризацию сверху и сосредоточьтесь только на дендрограмме слева от матрица.

Эта информация должна храниться в хранимой переменной dendrogram Z. Существует функция, которая должна выполнять только то, что я хочу назвать fcluster (см. Документацию здесь). Однако я не вижу, где я могу дать fcluster тот же самый cutoff, как я указал при создании дендрограммы. Похоже, что пороговая переменная в fcluster, t должна быть в виде различных неясных измерений (inconsistent, distance, maxclust, monocrit). Есть идеи?

4b9b3361

Ответ 1

Я думаю, ты на правильном пути. Попробуем это:

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 даст вам индексы кластера для каждого из 100 входных наблюдений. ind зависит от того, что method вы использовали в linkage. Попробуйте method=single, complete и average. Затем обратите внимание, как отличается ind.

Пример:

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 уверен, что это путает. В вашей ссылке я даже не узнаю свой собственный код!

Ответ 2

Я написал некоторый код, чтобы разложить матрицу связей. Он возвращает словарь, содержащий индексы labels, которые сгруппированы на каждом этапе агломерации. Я только пробовал его по результатам кластеров связей complete. Клавиши запуска dict в len(labels)+1, потому что изначально каждая метка рассматривается как собственный кластер. Это может ответить на ваш вопрос.

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

Возврат:

{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]}

Ответ 3

Я знаю, что это очень поздно для игры, но я создал объект построения на основе кода из сообщения здесь. Он зарегистрирован на пипе, поэтому для установки вам просто нужно позвонить

pip install pydendroheatmap

просмотрите страницу проекта github здесь: https://github.com/themantalope/pydendroheatmap

Ответ 4

Вы также можете попробовать cut_tree, у него есть параметр высоты, который должен дать вам то, что вы хотите, если для ультраметрики.