我如何获得由 scipy.cluster.hierarchy 制作的树状图的子树

Posted

技术标签:

【中文标题】我如何获得由 scipy.cluster.hierarchy 制作的树状图的子树【英文标题】:how do I get the subtrees of dendrogram made by scipy.cluster.hierarchy 【发布时间】:2013-05-28 19:36:49 【问题描述】:

我对这个模块 (scipy.cluster.hierarchy) 感到困惑......但仍然有一些!

例如,我们有以下树状图:

我的问题是如何以一种很好的格式(比如 SIF 格式)提取彩色子树(每个子树代表一个簇)? 现在得到上图的代码是:

import scipy
import scipy.cluster.hierarchy as sch
import matplotlib.pylab as plt

scipy.randn(100,2)

d = sch.distance.pdist(X)

Z= sch.linkage(d,method='complete')

P =sch.dendrogram(Z)

plt.savefig('plot_dendrogram.png')

T = sch.fcluster(Z, 0.5*d.max(), 'distance')
#array([4, 5, 3, 2, 2, 3, 5, 2, 2, 5, 2, 2, 2, 3, 2, 3, 2, 5, 4, 5, 2, 5, 2,
#       3, 3, 3, 1, 3, 4, 2, 2, 4, 2, 4, 3, 3, 2, 5, 5, 5, 3, 2, 2, 2, 5, 4,
#       2, 4, 2, 2, 5, 5, 1, 2, 3, 2, 2, 5, 4, 2, 5, 4, 3, 5, 4, 4, 2, 2, 2,
#       4, 2, 5, 2, 2, 3, 3, 2, 4, 5, 3, 4, 4, 2, 1, 5, 4, 2, 2, 5, 5, 2, 2,
#       5, 5, 5, 4, 3, 3, 2, 4], dtype=int32)

sch.leaders(Z,T)
# (array([190, 191, 182, 193, 194], dtype=int32),
#  array([2, 3, 1, 4,5],dtype=int32))

所以现在,fcluster() 的输出给出了节点的聚类(通过它们的 id),而 leaders() 描述的 here 应该返回 2 个数组:

第一个包含 Z 生成的集群的领导节点,这里我们可以看到我们有 5 个集群,以及在图中

第二个是这些集群的 id

所以如果这个领导者()返回相应的。 L 和 M :L[2]=182M[2]=1,然后集群 1 由节点 id 182 引导,这在观察集 X 中不存在,文档说“......那么它对应于非单例集群” .但我无法得到它......

另外,我通过sch.to_tree(Z) 将 Z 转换为树,这将返回一个易于使用的树对象,我想将其可视化,但我应该使用哪个工具作为操作这些类型的图形平台树对象作为输入?

【问题讨论】:

【参考方案1】:

回答您关于树操作的部分问题...

如aother answer 中所述,您可以从树对象中读取icoorddcoord 的分支坐标。对于每个分支,坐标从左到右给出。

如果你想手动绘制树,你可以使用类似的东西:

def plot_tree(P, pos=None):
    plt.clf()
    icoord = scipy.array(P['icoord'])
    dcoord = scipy.array(P['dcoord'])
    color_list = scipy.array(P['color_list'])
    xmin, xmax = icoord.min(), icoord.max()
    ymin, ymax = dcoord.min(), dcoord.max()
    if pos:
        icoord = icoord[pos]
        dcoord = dcoord[pos]
        color_list = color_list[pos]
    for xs, ys, color in zip(icoord, dcoord, color_list):
        plt.plot(xs, ys, color)
    plt.xlim(xmin-10, xmax + 0.1*abs(xmax))
    plt.ylim(ymin, ymax + 0.1*abs(ymax))
    plt.show()

在您的代码中,plot_tree(P) 给出:

该功能允许您只选择一些分支:

plot_tree(P, range(10))

现在您必须知道要绘制哪些分支。也许fcluster() 输出有点模糊,另一种根据最小和最大距离公差找到要绘制的分支的方法是直接使用linkage() 的输出(在OP 的情况下为Z):

dmin = 0.2
dmax = 0.3
pos = scipy.all( (Z[:,2] >= dmin, Z[:,2] <= dmax), axis=0 ).nonzero()
plot_tree( P, pos )

推荐参考:

How does condensed distance matrix work? (pdist) how to plot and annotate hierarchical clustering dendrograms in scipy/matplotlib

【讨论】:

这个答案帮助我找到了可以绘制树状图子树的位置,并在给定的表型距离 (PD) 内发现观察结果。我没有发现 fcluster 或 fclusterdata 方法对此有用。我使用了 sch.to_tree(linkage).pre_order(),然后通过参考 pdist 距离矩阵(参见***.com/a/17870926/1876324)顺序测试该列表中的相邻项目是否在 PD 内,然后重新计算每个项目的距离、链接和树状图我想绘制的组。例如,PD 为 4 会将 OP 数据分组到所需的 3 个子树中。 请注意,我需要在 plot_tree 函数的内容之前调用 plt.clf(),否则会显示完整的树状图。

以上是关于我如何获得由 scipy.cluster.hierarchy 制作的树状图的子树的主要内容,如果未能解决你的问题,请参考以下文章

如何获得一个散点矩阵,仅由具有 1:1 线的散点图和良好的轴标签组成?

如何获得由等高线图绘制的线的 (x,y) 值?

如何在 xamarin 表单中获得更多输入?

Java中如何由枚举常量的ordinal值获得枚举常量对象

Java中如何由枚举常量的ordinal值获得枚举常量对象

Java中如何由枚举常量的ordinal值获得枚举常量对象