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

基于data.table高效计算系统发育世代与进化枝内距离统计的方法求助

高效计算各世代进化枝内符合距离阈值的类群对统计量

问题背景

我有4个系统发育树的分类单元(taxa),将系统发育树划分为不同“世代”,用来确定每个世代下的进化枝(clades)。示例数据如下:

library(data.table)
clades = data.table(generation = rep(c("g0", "g4"), each = 4),
                    taxa = rep(c(LETTERS[1:4]), times = 2),
                    clade = c(1:4, 1, 1, 2, 2)
                    )
  • 世代g0:所有分类单元彼此独立,每个taxa对应单独的进化枝
  • 世代g4:A与B同属进化枝1,C与D同属进化枝2

同时我存储了各分类单元间的地理距离,采用长格式存储:

distance = data.table(
    row = c("A", "A", "B", "A", "B", "C"),
    col = c("B", "C", "C", "D", "D", "D"), 
    value = c(1.41, 5.65, 5.83, 5.83, 5.65, 1.41)
  )

需求

需要高效计算每个世代、每个进化枝内:

  • 距离小于阈值(本示例阈值为2)的类群对数量(分子)
  • 该进化枝内的总类群比对数(分母)
    进而得到类群距离符合阈值的概率。

先给距离数据添加阈值标记列:

distance$cut = distance$value < 2

本示例的预期结果如下:

result = data.table(generation = c("g0", "g0", "g0", "g0", "g4", "g4"),
                    clade = c(1, 2, 3, 4, 1, 2),
                    numerator = c(0, 0, 0, 0, 1, 1),
                    denominator = c(0, 0, 0, 0, 1, 1))

现有问题

我已通过*apply系列函数实现功能,但效率极低,无法支持大规模数据处理,现寻求高效实现方案。原实现代码:

generations = unique(clades$generation)
output = lapply(generations, function(g) {
  generation_df = clades[clades$generation == g]
  clade_sets <- unique(generation_df$clade)
  
  clade_result <- sapply(clade_sets, function(cs) {
    clade_taxa = generation_df$taxa[generation_df$clade == cs]
    trait = distance$trait[distance$row %in% clade_taxa & distance$col %in% clade_taxa]
    
    if (length(trait) >= 1) {
      numerator = sum(trait)
      denominator = length(trait)
    } else {
      numerator = 0
      denominator = 0
    }
    list(numerator = numerator, denominator = denominator)
  })
  
  # Combine clade result with generation and clade information
  data.frame(
    generation = g,
    clade = clade_sets,
    numerator = unlist(clade_result[1, ]),
    denominator = unlist(clade_result[2, ]),
    stringsAsFactors = FALSE
  )
})
dplyr::bind_rows(output)

高效实现方案

使用data.table的向量化连接与分组操作,完全避免循环,大幅提升大数据量下的处理效率:

library(data.table)

# 原始数据初始化
clades = data.table(generation = rep(c("g0", "g4"), each = 4),
                    taxa = rep(c(LETTERS[1:4]), times = 2),
                    clade = c(1:4, 1, 1, 2, 2)
                    )

distance = data.table(
    row = c("A", "A", "B", "A", "B", "C"),
    col = c("B", "C", "C", "D", "D", "D"), 
    value = c(1.41, 5.65, 5.83, 5.83, 5.65, 1.41)
  )

# 添加距离阈值标记
distance[, cut := value < 2]

# 关联每个配对的row和col对应的世代与进化枝信息
distance_clade = distance[clades, on = .(row = taxa), nomatch = 0, 
                          .(generation, clade_row = clade, row, col, cut)]
distance_clade = distance_clade[clades, on = .(generation, col = taxa), nomatch = 0, 
                                .(generation, clade, cut)]

# 筛选出同一进化枝内的配对
distance_clade = distance_clade[clade_row == clade]

# 按世代和进化枝分组统计
stats = distance_clade[, .(numerator = sum(cut), denominator = .N), by = .(generation, clade)]

# 补充无配对的进化枝并填充0
full_result = unique(clades[, .(generation, clade)])[stats, on = .(generation, clade)]
full_result[, `:=`(numerator = fifelse(is.na(numerator), 0, numerator), 
                   denominator = fifelse(is.na(denominator), 0, denominator))]

# 输出结果
full_result

方案优势

  1. 向量化操作:全程使用data.table的向量化接口,避免循环带来的性能损耗
  2. 高效连接:通过键连接一次性关联所有配对的进化枝信息,比逐次筛选快得多
  3. 完整结果:自动补充无配对的进化枝,保证结果与预期完全一致
  4. 可扩展性:处理百万级数据时,性能远优于apply系列函数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 19:50:33