如何基于cutree标签从hclust/dendrogram对象提取子树?
如何从hclust生成的树状图中提取对应簇的子树?
我明白你现在的需求:已经用hclust的ward.D方法完成聚类,通过cutree拿到了每个样本的簇标签,也能提取簇对应的数据,但想直接获取每个簇对应的子树结构,而不是单纯的数据集。直接用dnd[clusters == 1]肯定不行,因为树状图的结构不是按样本索引直接访问的,得用专门的方法来处理。
下面给你两种可行的方案,结合你的iris示例代码来演示:
方案一:用dendextend::get_subdendrograms直接按簇数提取子树
如果你是通过cutree(dnd, k=6)得到的6个簇,那这个方法最直接——get_subdendrograms可以直接把树状图分割成指定数量的子树,每个子树正好对应一个簇:
library(gplots) library(dendextend) # 你的原始代码 data <- iris[,1:4] distance <- dist(data, method = "euclidean", diag = FALSE, upper = FALSE) hc <- hclust(distance, method = 'ward.D') dnd <- as.dendrogram(hc) clusters <- cutree(dnd, k = 6) # 提取6个子树,每个子树对应一个簇 sub_dends <- get_subdendrograms(dnd, k = 6) # 可以单独查看某个子树,比如第1个簇的子树 plot(sub_dends[[1]], main = "第1个簇的子树")
这个方法的好处是一步到位,子树的顺序和cutree得到的簇标签顺序是对应的,比如sub_dends[[1]]就是所有clusters == 1的样本组成的子树。
方案二:自定义簇标签时,用prune修剪出指定叶子的子树
如果你的簇标签不是通过cutree(dnd, k=6)得到的(比如手动调整过簇划分),可以用prune函数,根据簇对应的样本叶子来修剪出子树:
# 假设我们已经有了clusters标签,现在提取第1个簇的样本名称/索引 cluster1_leaves <- rownames(data)[clusters == 1] # 修剪树状图,只保留这些叶子对应的子树 sub_dend_c1 <- prune(dnd, cluster1_leaves) # 绘制子树 plot(sub_dend_c1, main = "第1个簇的子树")
这里需要注意:如果你的数据集没有行名,rownames(data)会是默认的索引(比如1,2,...150),这也可以直接用来修剪,因为树状图的叶子默认是用样本索引命名的。
验证子树对应关系
如果你想确认子树的叶子确实对应簇里的样本,可以用labels()函数查看子树的叶子标签:
# 查看第1个子树的叶子标签 labels(sub_dends[[1]]) # 和clusters ==1的样本索引对比,应该完全一致 rownames(data)[clusters ==1]
这样就能确保你提取的子树和对应的簇是完全匹配的啦。
内容的提问来源于stack exchange,提问作者lucacerone




