You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

系统发育树多个体性状分析:ape库表型与树节点不匹配求解

解决APE库中表型数据与系统发育树末端数量不匹配的问题

嗨,作为系统发育分析的新手,你遇到的这个问题非常常见——当同一物种有多个表型样本,但树只有物种级别的末端时,确实会出现长度不匹配的错误。答案是肯定的:你可以通过构建polytomy(多歧节点)来拆分单个物种末端为多个样本,这样就能让树的末端数量和表型数据的样本数对齐。

下面一步步帮你修改代码,解决这个问题:

1. 理解问题根源

你的树来自10ktrees,包含28个物种级末端,但表型数据有34个样本(部分物种有多个个体)。pic()函数要求性状向量的长度必须和树的末端数量完全一致,所以我们需要调整树的结构,给每个多样本物种添加对应数量的末端节点,用polytomy来表示这些个体的关系(因为同一物种的个体没有显著的系统发育分化)。

2. 调整系统发育树的结构

我们可以用ape包的drop.tip()bind.tip()函数来修改树,把单个物种末端拆分成多个带后缀的末端节点,且这些节点共享同一个父节点(形成polytomy),分支长度设为0(因为同一物种个体间没有进化距离):

library(ape)

# 读取原始树和表型数据
tree <- read.nexus("10ktree.nex") 
pheno <- read.csv("pheno.csv")

# 统计每个物种的样本数量
sample_counts <- table(pheno$GenBank.Name)

# 遍历所有有多个样本的物种,拆分树的末端
for (sp in names(sample_counts)[sample_counts > 1]) {
  # 找到该物种在树中的末端索引
  tip_idx <- which(tree$tip.label == sp)
  # 获取该末端对应的父节点编号
  parent_node <- tree$edge[tree$edge[, 2] == tip_idx, 1]
  # 移除原来的物种末端
  tree <- drop.tip(tree, sp)
  # 为每个样本添加新的末端节点,形成polytomy
  for (i in 1:sample_counts[sp]) {
    # 给新末端命名(比如原物种名_1、原物种名_2)
    new_tip <- paste0(sp, "_", i)
    # 添加新末端,分支长度设为0,父节点为原物种的父节点
    tree <- bind.tip(tree, tip.label = new_tip, edge.length = 0, where = parent_node)
  }
}

# 处理只有单个样本的物种,保持命名格式统一
single_sample_sp <- names(sample_counts)[sample_counts == 1]
for (sp in single_sample_sp) {
  tip_idx <- which(tree$tip.label == sp)
  tree$tip.label[tip_idx] <- paste0(sp, "_1")
}

3. 调整表型数据的命名,匹配树的新末端

接下来我们需要把表型数据的样本名也改成和树末端一致的格式(比如原物种名_1、原物种名_2):

# 给表型数据的每个样本添加序号后缀
pheno$New_Tip_Name <- paste0(pheno$GenBank.Name, "_", ave(rep(1, nrow(pheno)), pheno$GenBank.Name, FUN = seq_along))

# 提取BrainVolume性状,并用新的样本名命名
BrainVolume <- pheno$BrainVolume
names(BrainVolume) <- pheno$New_Tip_Name

# 现在运行pic()就不会报错了!
pic.BrainVolume <- pic(BrainVolume, tree)

关键说明

  • 为什么用polytomy?:同一物种的多个个体属于同一个进化单元,没有足够的系统发育分化,用分支长度为0的polytomy来表示它们的关系是合理的,既符合生物学逻辑,也满足pic()函数的格式要求。
  • 命名一致性:一定要确保表型数据的新名字和树的末端名字完全匹配(包括大小写、后缀格式),否则依然会出现匹配错误。
  • 分支长度:设置edge.length = 0是因为同一物种个体间没有进化距离,如果你有个体间的遗传距离数据,也可以替换成对应的数值。

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

火山引擎 最新活动