使用R语言dendextend的get_subdendrograms时修改标签致子树为NULL
问题:修改 dendextend 树状图标签后生成子树出现 NULL
我使用 dendextend 包生成子树状图(subdendrograms),未修改叶节点标签时一切正常,但将标签改为'Y'或'B'后,多个子树变为 NULL。
可复现代码
library(dplyr) library(dendextend) new_labels <- c("Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y") new_colors <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 8, 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, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) # define dendrogram object to play with: dend <- iris[, -5] %>% dist() %>% hclust() %>% as.dendrogram() %>% # change the color of the labels set('labels_colors', new_colors[order.dendrogram(.)]) %>% # change the labels to 'Y' or 'B' set('labels', new_labels[order.dendrogram(.)]) %>% color_branches(k = 5) dend_list <- get_subdendrograms(dend, 5) # Plotting the result par(mfrow = c(2, 3)) plot(dend, main = "Original dendrogram") sapply(dend_list, plot)
问题原因
核心问题是重复标签干扰了子树拆分逻辑。get_subdendrograms函数依赖树状图叶节点的唯一标识来定位并拆分出子树,当你将大量标签修改为重复的'Y'/'B'后,函数无法区分不同的叶节点,导致无法准确识别每个子树对应的节点集合,最终返回NULL。
解决方法
方法1:先拆分子树,再修改标签(推荐)
先基于原始唯一标签完成子树拆分,再逐个修改每个子树的显示标签和颜色,这样既保证拆分逻辑的正确性,又能实现所需的显示效果:
library(dplyr) library(dendextend) new_labels <- c("Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "B", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y") new_colors <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 8, 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, 8, 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. 先构建树状图,保留原始唯一标签,完成子树拆分 dend <- iris[, -5] %>% dist() %>% hclust() %>% as.dendrogram() %>% color_branches(k = 5) dend_list <- get_subdendrograms(dend, 5) # 2. 对每个子树单独设置标签和颜色 dend_list <- lapply(dend_list, function(sub_dend) { # 获取当前子树叶节点的原始顺序索引 sub_order <- order.dendrogram(sub_dend) # 匹配对应的新标签和颜色 sub_labels <- new_labels[sub_order] sub_colors <- new_colors[sub_order] # 应用到子树 sub_dend %>% set('labels_colors', sub_colors) %>% set('labels', sub_labels) }) # 3. 修改原始树的标签和颜色用于对比展示 dend <- dend %>% set('labels_colors', new_colors[order.dendrogram(.)]) %>% set('labels', new_labels[order.dendrogram(.)]) # 绘图展示 par(mfrow = c(2, 3)) plot(dend, main = "Original dendrogram") sapply(dend_list, plot)
方法2:保留原始标签,仅修改显示样式(可选)
如果不需要修改底层标签的唯一标识,只是想改变显示的文本样式,可以通过自定义绘图函数实现,避免修改labels属性影响拆分逻辑。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

