如何在 scipy 创建的树状图中获得与颜色簇相对应的平面聚类

Posted

技术标签:

【中文标题】如何在 scipy 创建的树状图中获得与颜色簇相对应的平面聚类【英文标题】:How to get flat clustering corresponding to color clusters in the dendrogram created by scipy 【发布时间】:2011-12-01 15:57:00 【问题描述】:

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

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

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

【问题讨论】:

请注意,如果您的D 是对称距离矩阵,那么您就错了。相反,linkage() 的输入应该是一个 n-choose-2 数组,就像 @Steve 所做的那样。 【参考方案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 取决于您在 linkage 中使用的 method。试试method=singlecompleteaverage。然后注意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 确实令人困惑。在您的链接中,我什至不认识自己的代码!

【讨论】:

没错。这里的主要问题是 fcluster 函数采用了几个距离度量。其中之一恰好被称为“距离”。据我所知,scipy 文档没有提到绘制和着色树状图的树状图函数也使用“距离”度量来计算距离。那是混乱造成的。感谢您清理它。 @史蒂夫。我正在尝试使用 100 个 2d 向量的随机集将代码调整为测试数据,但我收到此错误:文件“mycluster.py”,第 61 行,在 main() 文件“mycluster.py”,行58,在主集群(数据)文件“mycluster.py”,第46行,集群cmap = pylab.cm.YlGnBu)文件“/usr/lib/pymodules/python2.7/matplotlib/axes.py”,第7704行, 在 matshow nr, nc = Z.shape ValueError: need more than 1 value to unpack 还有ind代表什么。这些 1 是什么? ind 是每个观察的集群索引。在此示例中,有 100 个观测值,因此有 100 个聚类索引,每个观测值一个。关于你的第一个问题,我不知道。【参考方案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】:

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

pip install pydendroheatmap

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

【讨论】:

【参考方案4】:

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

【讨论】:

以上是关于如何在 scipy 创建的树状图中获得与颜色簇相对应的平面聚类的主要内容,如果未能解决你的问题,请参考以下文章

显示scipy树状图的簇标签

scipy树状图中的倒置分支

如何从 MATLAB 中的树状图中获取颜色?

在距离高度从 SciPy 切割树状图/聚类树

在 Scipy/Matplotlib 中注释树状图节点

在 Scipy 错误中为大型数据集绘制树状图