我很难为数字范围上的键连接创建快速的 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))
我想向variantMatrix返回一个名为covered_alleles的列,如果variantMatrix的start:end中的所有位置都被覆盖> = 10(取自coverageTable中的coverage列),则该列的值为2,如果不满足此条件,则返回值为0 .
目前,我正在使用以下代码,该代码可以工作,但速度很慢:
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
但是,我需要在数百万个变体上运行此代码,因此将此函数逐行应用于variantMatrix 的速度非常慢。有没有办法使用 data.table 语法来使此操作更快?谢谢!
我建议对
coverageTable
进行基于范围的联接,以确定每个 variantMatrix
行属于哪一行,然后根据值汇总这些行。
## "unique id" for each row
variantMatrix[, rn := .I]
coverageTable[variantMatrix, rn := i.rn,
on = .(position >= start, position <= end)]
# position coverage rn
# <int> <num> <int>
# 1: 1 15 1
# 2: 2 5 2
# 3: 3 20 3
# 4: 4 15 3
# 5: 5 9 4
# 6: 6 11 4
最后,
variantMatrix[
coverageTable[, .(covered_alleles = fifelse(all(coverage >= 10), 2L, 0L)), by = "rn"],
on = "rn"]
# start end rn covered_alleles
# <num> <num> <int> <int>
# 1: 1 1 1 2
# 2: 2 2 2 0
# 3: 3 4 3 2
# 4: 5 6 4 0
这样做的副作用是
coverageTable$rn
存在,很容易清理。