19

使用此处发布的代码,我创建了一个不错的层次聚类:

scipy 树状图

假设左侧的树状图是通过执行类似的操作创建的

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(请参阅此处的文档)。但是,我看不到在哪里可以提供cutoff与创建树状图时指定的 fcluster 相同的位置。似乎 , 中的阈值变量fcluster必须t根据各种模糊的测量值 ( inconsistent, distance, maxclust, monocrit)。有任何想法吗?

4

4 回答 4

19

我认为你在正确的轨道上。让我们试试这个:

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,completeaverage. 然后注意有什么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确实令人困惑。在您的链接中,我什至不认识自己的代码!

于 2011-10-05T22:52:23.900 回答
5

我写了一些代码来解压缩链接矩阵。它返回一个字典,其中包含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]}
于 2017-04-02T16:20:26.640 回答
1

我知道这对游戏来说已经很晚了,但是我根据此处帖子中的代码制作了一个绘图对象。它在 pip 上注册,所以要安装你只需要调用

pip install pydendroheatmap

在此处查看项目的 github 页面:https ://github.com/themantalope/pydendroheatmap

于 2015-07-14T03:56:58.203 回答
1

你也可以试试cut_tree,它有一个高度参数,可以为你提供你想要的超度量。

于 2017-12-14T21:29:57.860 回答