R使用ape包修改fan类型聚类树标签 按分组配置分支与末端颜色
R语言ape包绘制聚类扇形树实现方案
核心问题修正点
你之前自定义标签失败的核心原因有三个:
show.tip.label是纯逻辑参数,仅控制标签是否显示,不接受标签向量输入,标签是从phylo对象的tip.label字段自动读取的- 做聚类前没有把矩阵行名设置为哨声亚型名称,导致hclust默认用行号(数值)作为标签,后续手动匹配标签时容易出现长度不一致、顺序错位,触发空向量、内存报错
tip.color参数需要传入和tip.label长度完全一致、顺序一一对应的颜色向量,不是全局设置参数,顺序错了颜色就会乱
分步实现代码
1. 加载依赖包
library(ape) library(RColorBrewer)
2. 数据格式转换(聚类前置步骤)
层次聚类要求输入为行=聚类对象(哨声亚型)、列=分组变量(国家)、值=计数N的数值矩阵,原始长表结构不能直接用于计算距离:
# 长表转宽表,同哨声亚型同国家的多条计数做求和聚合 whistle_agg <- aggregate(N ~ Whistle_Type_Sub + Country, data = Sub_Whistle_Count, FUN = sum) whistle_wide <- reshape( whistle_agg, idvar = "Whistle_Type_Sub", timevar = "Country", direction = "wide", v.names = "N" ) # 关键步骤:将行名设置为哨声亚型名称,后续树标签自动读取行名 rownames(whistle_wide) <- whistle_wide$Whistle_Type_Sub # 提取数值矩阵,缺失值(该国家无对应哨声记录)补0 whistle_mat <- as.matrix(whistle_wide[, grep("^N\\.", colnames(whistle_wide))]) whistle_mat[is.na(whistle_mat)] <- 0
3. 构建聚类树对象
# 计算距离矩阵做层次聚类,计数数据推荐用ward.D2聚类方法 hc <- hclust(dist(whistle_mat, method = "euclidean"), method = "ward.D2") # 转为ape包支持的phylo对象,此时tip.label自动为哨声亚型名称 tree <- as.phylo(hc)
4. 配色映射(标签+分支边同色)
调用Dark2调色板,按国家映射颜色,分支边颜色和所属聚类的国家标签保持一致:
# 3个国家对应Dark2调色板前3色 country_color <- brewer.pal(3, "Dark2") names(country_color) <- levels(Sub_Whistle_Count$Country) # 按树的tip.label顺序匹配每个哨声对应的国家、标签颜色 tip_meta <- data.frame( tip = tree$tip.label ) tip_meta$Country <- Sub_Whistle_Count$Country[match(tip_meta$tip, Sub_Whistle_Count$Whistle_Type_Sub)] tip_color <- country_color[as.character(tip_meta$Country)] # 匹配分支边颜色:仅完全属于单个国家的分支用对应颜色,跨国家内部分支用黑色 edge_color <- rep("#000000", nrow(tree$edge)) tip_part <- prop.part(tree) for (i in seq_len(nrow(tree$edge))) { current_node <- tree$edge[i, 2] # 提取当前节点下游所有末端tip if (current_node <= length(tree$tip.label)) { desc_tips <- current_node } else { desc_tips <- tip_part[[current_node - length(tree$tip.label)]] } # 判断下游tip是否全部属于同一国家 country_unique <- unique(tip_meta$Country[desc_tips]) if (length(country_unique) == 1) { edge_color[i] <- country_color[as.character(country_unique)] } }
5. 绘制扇形树状图
plot( tree, type = "fan", show.tip.label = TRUE, tip.color = tip_color, edge.color = edge_color, edge.width = 1.2, cex = 0.75, font = 1, no.margin = TRUE ) # 添加国家图例 legend( "topleft", legend = names(country_color), col = country_color, pch = 15, bty = "n", title = "采样国家" )
常见报错排查
- 出现空标签/数值标签:检查聚类矩阵的行名是否正确设置为
Whistle_Type_Sub取值,必须在hclust()调用前完成行名赋值 - 出现内存解压缩错误:检查传入的
tip.color向量长度是否和tree$tip.label长度完全一致,顺序是否一一对应,不要用全局匹配函数做无序匹配 - 边颜色错乱:检查边色循环里的节点索引逻辑,不要手动修改
tree$edge矩阵的顺序
内容的提问来源于stack exchange,提问作者Alice Hobbs
相关产品推荐
相关产品推荐

