基于hclust的聚类分支标注与树切割需求技术问询
针对你的两个需求和疑问,直接给你具体的R实现方案和解释:
需求1:在聚类树分支根部标注相关度
hclust的树高默认是距离值,如果你的距离矩阵是用1 - cor(seq_matrix)生成的(相关性越高,距离越小),那相关度可通过1 - 树高转换为百分比。推荐用ggtree包实现标注,代码示例:
library(ggtree) library(dplyr) # 假设你已生成hclust结果:hc hc <- hclust(dist(1 - cor(seq_matrix)), method = "complete") # 转换为phylo格式(ggtree支持的树对象) tree <- as.phylo(hc) # 将树高转换为相关度并生成百分比标签 tree$edge.length <- 1 - tree$edge.length tree$edge.label <- paste0(round(tree$edge.length * 100, 1), "%") # 绘制带标注的聚类树 ggtree(tree) + geom_text(aes(label = edge.label), hjust = -0.1, size = 3) + geom_tiplab(size = 3)
如果你的距离计算方式不同(比如默认欧氏距离),需要对应调整相关度的转换逻辑。
需求2:切割聚类树并实现三种分支命名方案
首先手动定义目标分组:
- 单序列组:
c("r4", "e", "r12", "r21ee", "r2") - 聚类A:
c("r.is.almost.r1", "r1", "r.is.r1") - 聚类B:
c("r21", "r21e")
步骤1:构建自定义分组
# 获取所有序列名称 all_seqs <- hc$labels # 创建分组向量 group <- rep(NA, length(all_seqs)) names(group) <- all_seqs # 给单序列组赋值(每个单独成组) single_seqs <- c("r4", "e", "r12", "r21ee", "r2") group[single_seqs] <- single_seqs # 给聚类A、B赋值 group[c("r.is.almost.r1", "r1", "r.is.r1")] <- "Cluster_A" group[c("r21", "r21e")] <- "Cluster_B"
三种命名方案实现
方案1:合并名称(组内所有序列名拼接)
# 定义名称合并函数 merge_names <- function(seq_names) { paste(seq_names, collapse = "_") } # 生成合并后的组名 named_groups <- tapply(names(group), group, merge_names) # 示例结果:Cluster_A -> "r.is.almost.r1_r1_r.is.r1"
方案2:选中心序列(组内平均距离最小的序列)
# 获取距离矩阵 dist_mat <- as.matrix(dist(1 - cor(seq_matrix))) # 定义找中心序列的函数 find_center <- function(seq_names) { # 计算组内每个序列到其他序列的平均距离 avg_dist <- apply(dist_mat[seq_names, seq_names], 1, mean) # 返回平均距离最小的序列名 names(which.min(avg_dist)) } # 生成以中心序列命名的组名 named_groups <- tapply(names(group), group, find_center) # 示例结果:Cluster_A -> 三个序列中平均距离最小的那个(比如r1)
方案3:指定优先名称(按预设优先级选取)
# 预设优先级列表(按你想要的优先顺序排列) priority_list <- c("r1", "r21", "r4", "e", "r12", "r21ee", "r2") # 定义找优先名称的函数 find_priority <- function(seq_names) { # 从优先级列表中取第一个出现在组内的序列 priority_list[priority_list %in% seq_names][1] } # 生成按优先级命名的组名 named_groups <- tapply(names(group), group, find_priority) # 示例结果:Cluster_A -> "r1"(因r1在优先级列表中)
疑问解答
1. 聚类树的树高含义
hclust的树高代表两个簇合并时的距离值,具体含义完全取决于你最初计算的距离矩阵:
- 若用
1 - cor(seq_matrix)作为距离:树高越小,簇间平均相关性越高;树高为0时,相关性100%。 - 若用默认欧氏距离:树高代表簇间样本的平均欧氏距离,数值越小说明簇内样本越相似。
简言之:树高是簇间相似性的反向指标——树高越小,簇越相似。
2. 负相关序列为何会被聚类?
这完全取决于你使用的距离计算方式:
- 若用
1 - abs(cor(seq_matrix)):正相关和负相关的距离值一致(取了绝对值),负相关序列会被判定为“相似”,从而被聚在一起。 - 若用
1 - cor(seq_matrix):负相关时cor值为负,距离会变成1 - 负数 = 大于1的数值,距离极大,几乎不会被聚在一起。
先检查你的距离计算代码,确认是否误用了带绝对值的相关距离函数。
内容的提问来源于stack exchange,提问作者ivo Welch
相关产品推荐
相关产品推荐

