如何用dendextend包提取R树状图节点坐标及分支起止/子节点信息
获取dendextend树状图的分支起止位置与节点子节点信息
一、获取所有节点的子节点信息
你可以通过dendextend::get_children()函数结合遍历提取每个节点的子节点;也可以用递归函数解析树状图结构,得到更清晰的层级关系。
方法1:遍历所有节点提取子节点
library(dendextend) # 示例树状图(替换为你的树状图对象) hc <- hclust(dist(iris[,1:4])) dend <- as.dendrogram(hc) # 获取所有节点的ID(叶子+内部节点) all_node_ids <- seq_len(nleaves(dend) + ninternals(dend)) # 遍历每个节点,提取子节点(叶子节点返回NULL) node_children_list <- lapply(all_node_ids, function(id) { current_node <- dend[[id]] if (is.leaf(current_node)) NULL else get_children(current_node) }) # 命名列表,方便对应节点查看 names(node_children_list) <- paste0("node_", all_node_ids)
方法2:递归函数解析完整树结构
如果需要更直观的层级关系,用递归函数可以输出每个节点的路径和子节点:
get_full_tree_structure <- function(dend_node, node_path = c()) { if (is.leaf(dend_node)) { return(list(type = "leaf", label = attr(dend_node, "label"), path = node_path)) } else { child_nodes <- lapply(seq_along(dend_node), function(i) { get_full_tree_structure(dend_node[[i]], c(node_path, i)) }) return(list(type = "internal", path = node_path, children = child_nodes)) } } # 生成完整结构 tree_structure <- get_full_tree_structure(dend)
二、直接获取分支起止位置
如果不想自行计算,可通过dendrogram_to_gg()将树状图转换为ggplot对象,直接提取所有分支的线段数据:
# 转换为ggplot对象 gg_dend_obj <- dendrogram_to_gg(dend) # 提取分支起止数据:包含x, xend, y, yend字段 branch_segments_data <- gg_dend_obj$data
如果要手动计算分支起止,可结合节点坐标和子节点信息:
# 获取所有节点坐标 nodes_xy <- get_nodes_xy(dend) # 筛选内部节点(非叶子节点) internal_node_ids <- which(!sapply(dend, is.leaf)) # 计算每个内部节点对应的分支线段 branch_details <- lapply(internal_node_ids, function(node_id) { parent_xy <- nodes_xy[node_id, ] child_nodes <- get_children(dend[[node_id]]) # 匹配子节点的ID child1_id <- which(sapply(dend, function(n) identical(n, child_nodes[[1]]))) child2_id <- which(sapply(dend, function(n) identical(n, child_nodes[[2]]))) child1_xy <- nodes_xy[child1_id, ] child2_xy <- nodes_xy[child2_id, ] # 返回各段分支的起止坐标 list( vertical_child1 = list(start = c(child1_xy[1], child1_xy[2]), end = c(child1_xy[1], parent_xy[2])), horizontal_parent = list(start = c(child1_xy[1], parent_xy[2]), end = c(child2_xy[1], parent_xy[2])), vertical_child2 = list(start = c(child2_xy[1], parent_xy[2]), end = c(child2_xy[1], child2_xy[2])) ) }) names(branch_details) <- paste0("branch_", internal_node_ids)
内容的提问来源于stack exchange,提问作者Robin Paul
相关产品推荐
相关产品推荐

