R circlize绘制扇形树状图标签重复报错及配色问题咨询
解决方案
问题根因
circlize::circlize_dendrogram() 内置逻辑强制要求树状图的全局末端标签唯一,不会识别「分组内标签唯一」的业务规则,因此跨国家出现同名哨声亚型时,会自动给标签追加连续序号。如果构建树对象时没有按树的叶子排列顺序匹配元数据,还会出现标签和国家分组错位、同组下显示重复哨声类型的逻辑错误。
分步实现
- 从根源关闭自动追加序号的逻辑:不要依赖函数自带的标签绘制模块,调用时直接关闭内置标签轨道,即可完全跳过标签唯一性校验。聚类阶段先给每个样本生成全局唯一的临时ID用于树对象构建,避免触发重复警告;绘图时设置
labels_track_height = NA关闭自带标签,后续单独自定义标签轨道,支持显示重复的原始哨声亚型标签。 - 按国家分组匹配全元素配色:通过
dendextend包提前给树的分支、末端段、标签绑定对应国家的配色,直接将着色后的树对象传入绘图函数即可,不需要依赖函数内置配色规则。 - 修复标签错位导致的同组重复问题:所有叶子属性(标签、颜色、分组)的匹配,必须以树的叶子排列顺序、唯一样本ID为关联键,禁止直接按原始数据框的行顺序赋值,避免匹配错位。
可复现代码模板
# 加载依赖包 library(circlize) library(dendextend) # ---------------------- # 1. 数据预处理 # ---------------------- # 替换为你的原始数据:df需包含Country列、Whistle_Type_Sub列,以及用于聚类的数值特征列 # 生成全局唯一样本ID,作为树构建阶段的临时标签 df$sample_id <- paste0(df$Country, "_", df$Whistle_Type_Sub) # 定义国家专属配色,可按需替换色值 country_pal <- c( "西班牙" = "#E64B35", "荷兰" = "#4DBBD5", "法国" = "#00A087" ) # 构造元数据映射表,以唯一sample_id为键 meta_map <- data.frame( sample_id = df$sample_id, country = df$Country, whistle_label = df$Whistle_Type_Sub, color = country_pal[df$Country], row.names = "sample_id" ) # ---------------------- # 2. 构建并着色树状图 # ---------------------- # 计算距离矩阵、聚类,替换为你实际使用的聚类方法/距离类型 feature_cols <- setdiff(colnames(df), c("Country", "Whistle_Type_Sub", "sample_id")) dist_matrix <- dist(df[, feature_cols], method = "euclidean") hc <- hclust(dist_matrix, method = "ward.D2") dend <- as.dendrogram(hc) # 按树的叶子顺序绑定唯一sample_id标签 labels(dend) <- df$sample_id[order.dendrogram(dend)] # 给树的分支、末端段按国家配色 dend <- color_branches(dend, col = meta_map[labels(dend), "color"]) # 给树的内置标签设置对应国家颜色(不需要内置标签可跳过此步) dend <- color_labels(dend, col = meta_map[labels(dend), "color"]) # ---------------------- # 3. 绘制环形树状图 # ---------------------- circos.clear() circos.par(start.degree = 90, gap.degree = 0) circos.initialize(factors = "dend", xlim = c(0, nobs(dend))) # 绘制树状图主体,关闭自带标签轨道 circos.track(ylim = c(0, 1), panel.fun = function(x, y) { circlize_dendrogram( dend = dend, dend_track_height = 0.8, labels_track_height = NA, # 关键参数:关闭内置标签,跳过重复校验 direction = "inside", border = NA ) }) # 自定义绘制标签轨道,显示原始哨声亚型标签,按国家配色 circos.track( ylim = c(0, 0.15), bg.border = NA, panel.fun = function(x, y) { leaf_order <- labels(dend) circos.text( x = 1:nobs(dend), y = 0.5, labels = meta_map[leaf_order, "whistle_label"], col = meta_map[leaf_order, "color"], facing = "clockwise", niceFacing = TRUE, adj = c(0, 0.5), cex = 0.6 ) } ) circos.clear()
注意事项
- 如果需要给分支按聚类簇着色而非全段按国家着色,可以在
color_branches中指定k(聚类簇数)参数,再单独给末端段、标签按国家覆盖颜色即可 - 标签朝向、字号、树的方向、轨道高度均可根据实际输出调整参数
- 只要以唯一
sample_id作为元数据匹配键,就不会出现标签错位、同组下重复显示哨声类型的问题
内容的提问来源于stack exchange,提问作者Alice Hobbs
相关产品推荐
相关产品推荐

