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

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

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)

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

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

Ответы [ 4 ]

18 голосов
/ 06 октября 2011

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

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 голосов
/ 02 апреля 2017

Я написал некоторый код для деконденсации матрицы связей. Он возвращает словарь, содержащий индексы 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]}
1 голос
/ 15 декабря 2017

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

1 голос
/ 14 июля 2015

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

pip install pydendroheatmap

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...