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

R中匹配拓扑相同的系统发育树节点以计算平均分支长度

解决方案

方法1:节点唯一标识匹配法(最稳妥)

核心逻辑:拓扑相同的两棵树,每个节点对应的所有后代末梢标签集合是唯一且固定的,不受节点存储顺序影响,我们可以把这个集合转为字符串作为匹配主键,实现100%准确的节点匹配。

代码实现

# 加载所需包
library(ape)
library(tidytree)
library(dplyr)
library(purrr)

# 自定义函数:生成节点唯一匹配键
get_node_key <- function(tree, node) {
  # 末梢节点直接返回自身标签作为键
  if (node <= ape::Ntip(tree)) {
    return(tree$tip.label[node])
  }
  # 内部节点取所有后代末梢标签,排序后拼接为唯一键
  descendant_tips <- ape::extract.clade(tree, node)$tip.label
  sort(descendant_tips) |> paste0(collapse = "|")
}

# 分别为两棵树的所有节点生成匹配键
t1_tbl <- tidytree::as_tibble(t1) |>
  mutate(node_key = map_chr(node, ~get_node_key(t1, .x)))
t2_tbl <- tidytree::as_tibble(t2) |>
  mutate(node_key = map_chr(node, ~get_node_key(t2, .x)))

# 按键匹配,计算分支长度平均值
match_result <- inner_join(
  t1_tbl |> select(node_key, label, bl_t1 = branch.length),
  t2_tbl |> select(node_key, bl_t2 = branch.length),
  by = "node_key"
) |> mutate(bl_avg = (bl_t1 + bl_t2)/2)

# 如果需要生成平均分支长度的新系统发育树,直接用t1的拓扑赋值即可
avg_tree <- t1
avg_tree$edge.length <- match_result$bl_avg[match(t1_tbl$node_key, match_result$node_key)]

方法2:补全matchNodes的末梢匹配

phytools::matchNodes默认仅返回内部节点的匹配结果,没有包含末梢节点,因此你之前看不到末梢的对应关系,手动补全末梢匹配即可得到完整的节点对应表:

代码实现

# 1. 匹配内部节点
inner_node_match <- phytools::matchNodes(t1, t2, method = "descendants")
colnames(inner_node_match) <- c("t1_node", "t2_node")

# 2. 匹配末梢节点(按标签直接匹配)
tip_node_match <- data.frame(
  t1_node = 1:ape::Ntip(t1),
  t2_node = match(t1$tip.label, t2$tip.label)
)

# 3. 合并得到所有节点的匹配表
all_node_match <- rbind(tip_node_match, inner_node_match)

# 4. 提取对应分支长度计算平均值
t1_bl <- t1$edge.length[match(all_node_match$t1_node, t1$edge[,2])]
t2_bl <- t2$edge.length[match(all_node_match$t2_node, t2$edge[,2])]
avg_bl <- (t1_bl + t2_bl)/2

内容的提问来源于stack exchange,提问作者dan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 07:15:02