如何在 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
相同的值。似乎fcluster
、t
中的阈值变量必须根据各种模糊的测量值(inconsistent
、distance
、maxclust
、monocrit
)。有任何想法吗?
【问题讨论】:
请注意,如果您的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=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
确实令人困惑。在您的链接中,我什至不认识自己的代码!
【讨论】:
没错。这里的主要问题是 fcluster 函数采用了几个距离度量。其中之一恰好被称为“距离”。据我所知,scipy 文档没有提到绘制和着色树状图的树状图函数也使用“距离”度量来计算距离。那是混乱造成的。感谢您清理它。 @史蒂夫。我正在尝试使用 100 个 2d 向量的随机集将代码调整为测试数据,但我收到此错误:文件“mycluster.py”,第 61 行,在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 创建的树状图中获得与颜色簇相对应的平面聚类的主要内容,如果未能解决你的问题,请参考以下文章