如何在R语言中找到树状图k分组下每组的最高节点?
如何用dendextend绘制k切割后各簇的最高节点?
我正在使用dendextend包在R语言中处理树状图,希望仅绘制按k值切割树后每个簇中高度最高的节点,想了解是否有便捷的实现方法?
可复现示例
###### sample tree ###### library(dendextend) library(dplyr) dend15 <- c(1:5) %>% dist() %>% hclust(method = "average") %>% as.dendrogram() ###### plotting with clusters based on k ####### ## 可以通过给set()函数传入NA向量来控制节点是否显示 node_xy <- get_nodes_xy(dend15) ## 获取所有节点的坐标 v <- rep(NA, nrow(node_xy)) ## 初始化与节点数长度一致的向量 v[c(2,5)] <- 19 ## 给节点2和5设置形状19(手动指定的节点) dend15 <- dend15 %>% set("nodes_pch",v) ## 设置节点形状 dend15 %>% plot(main="sample tree with highest nodes in k") dend15 %>% rect.dendrogram(k=2) ## 绘制k=2时的簇矩形

我希望能针对任意树状图和任意k值,自动确定需要绘制的节点。更宽泛地说,想了解如何结合cutree()和rect.dendrogram()的信息,通过dendextend的数据来控制节点显示。
更新:heights_per_k.dendrogram()函数会返回不同k值切割时的树高,可通过height @ k > node_h > height @ k+1筛选节点,但该方法无法覆盖单叶形成簇的情况(如示例中k=3时的场景)。
解决方案
要解决单叶簇的问题,我们可以通过簇的叶节点追溯所有相关节点,再筛选每个簇的最高节点的方式实现,具体步骤如下:
1. 定义获取各簇最高节点的函数
get_top_cluster_nodes <- function(dend, k) { # 获取每个叶节点的簇分配结果 cluster_assign <- cutree(dend, k = k) # 获取所有节点的关键信息:节点ID、高度、是否为叶节点 node_info <- dend %>% get_nodes_attr(c("label", "height", "leaf")) %>% mutate(node_id = row_number()) # 遍历每个簇,找出对应最高节点 top_nodes <- c() for (cluster in unique(cluster_assign)) { # 当前簇包含的所有叶节点 cluster_leaves <- names(cluster_assign[cluster_assign == cluster]) # 收集当前簇所有相关节点(叶节点+所有祖先节点) cluster_nodes <- c() for (leaf in cluster_leaves) { # 获取该叶节点的所有祖先节点ID ancestor_ids <- dend %>% get_leaf_ancestors(leaf) cluster_nodes <- c(cluster_nodes, ancestor_ids, which(node_info$label == leaf)) } cluster_nodes <- unique(cluster_nodes) # 筛选当前簇的节点,并找出高度最高的那个 top_node <- node_info[cluster_nodes, ] %>% arrange(desc(height)) %>% slice(1) %>% pull(node_id) top_nodes <- c(top_nodes, top_node) } return(top_nodes) }
2. 应用函数并绘图
# 设置目标k值 k <- 3 # 获取各簇最高节点ID top_nodes <- get_top_cluster_nodes(dend15, k) # 配置节点显示:仅保留目标节点,其余设为NA v <- rep(NA, nrow(get_nodes_xy(dend15))) v[top_nodes] <- 19 # 更新树状图的节点样式 dend15 <- dend15 %>% set("nodes_pch", v) # 绘制结果 plot(dend15, main = paste0("k=", k, "时仅显示各簇最高节点的树状图")) rect.dendrogram(dend15, k = k)
方法说明
cutree():快速获取每个叶节点的簇归属,明确每个簇包含的叶子get_leaf_ancestors():追溯叶节点的所有祖先节点,确保覆盖整个簇的所有层级节点- 按节点高度降序筛选:直接取每个簇中高度最高的节点(单叶簇的最高节点就是叶节点本身,完美覆盖边界场景)
- 通过
set("nodes_pch", v):用NA隐藏不需要显示的节点,仅保留目标节点
内容的提问来源于stack exchange,提问作者perechen
相关产品推荐
相关产品推荐

