You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 00:39:03