优化data.table行级函数:快速实现数值范围键连接
高效处理区间覆盖判断的data.table方案
问题背景
需要处理百万级变异数据,现有逐行调用函数的方式速度无法接受,需用更高效的data.table语法实现区间覆盖判断:为variantMatrix添加covered_alleles列,当start:end区间内所有位置在coverageTable中的coverage值均≥10时赋值为2,否则为0。
输入数据
library(data.table) coverageTable <- data.table('position' = c(1:6), 'coverage' = c(15, 5, 20, 15, 9, 11)) variantMatrix <- data.table('start' = c(1,2,3,5), 'end' = c(1,2,4,6))
现有低效代码
逐行调用自定义函数,速度极慢:
isCovered <- function( coverageTable, start, end ) { return(ifelse(all(coverageTable[.(start:end),coverage]>=10),2,0)) } setkey(coverageTable,position) variantMatrix[,covered_alleles:=isCovered(coverageTable,start,end),by=c('start','end')]
预期输出
start end covered_alleles <num> <num> <num> 1: 1 1 2 2: 2 2 0 3: 3 4 2 4: 5 6 0
高效解决方案
利用data.table的非等值连接和.EACHI分组聚合特性,避免逐行循环:
- 先预处理
coverageTable,标记每个位置是否达标:
coverageTable[, is_ok := coverage >= 10]
- 通过非等值连接关联两个表,按
variantMatrix的每一行(.EACHI)聚合判断:
result <- variantMatrix[coverageTable, on = .(start <= position, end >= position), .(covered_alleles = ifelse(all(is_ok), 2, 0)), by = .EACHI]
方案优势
- 非等值连接是data.table内部优化的向量式操作,远快于逐行循环;
.EACHI确保按variantMatrix的每一行进行分组计算,无需手动指定by参数;- 处理百万级数据时,性能提升可达数十倍甚至上百倍。
内容的提问来源于stack exchange,提问作者undercover_camel
相关产品推荐
相关产品推荐

