我认为这个问题有两个具有挑战性的部分。首先是寻找重叠。我会使用BioconductorIRanges
的包(在基本包中也可能有用)?findInterval
library(IRanges)
创建表示坐标向量的宽度为 1 的范围,以及表示分数的范围集;为方便起见,我对坐标向量进行排序,假设重复的坐标可以被同等对待
coord <- sort(sample(.Machine$integer.max, 5000000))
starts <- sample(.Machine$integer.max, 1200000)
scores <- runif(length(starts))
q <- IRanges(coord, width=1)
s <- IRanges(starts, starts + 100L)
在这里我们找到哪些query
重叠subject
system.time({
olaps <- findOverlaps(q, s)
})
这在我的笔记本电脑上大约需要 7 秒。有不同类型的重叠(请参阅 参考资料?findOverlaps
),因此这一步可能需要一些改进。结果是一对索引查询和重叠主题的向量。
> olaps
Hits of length 281909
queryLength: 5000000
subjectLength: 1200000
queryHits subjectHits
<integer> <integer>
1 19 685913
2 35 929424
3 46 1130191
4 52 37417
我认为这是第一个复杂部分的结尾,找到 281909 重叠。(我不认为其他地方提供的 data.table 答案解决了这个问题,尽管我可能弄错了......)
下一个具有挑战性的部分是计算大量均值。内置方式类似于
olaps0 <- head(olaps, 10000)
system.time({
res0 <- tapply(scores[subjectHits(olaps0)], queryHits(olaps0), mean)
})
这在我的计算机上大约需要 3.25 秒,并且似乎是线性缩放的,所以 280k 重叠可能需要 90 秒。但我认为我们可以使用data.table
. 原坐标start(v)[queryHits(olaps)]
为
require(data.table)
dt <- data.table(coord=start(q)[queryHits(olaps)],
score=scores[subjectHits(olaps)])
res1 <- dt[,mean(score), by=coord]$V1
所有 280k 重叠大约需要 2.5 秒。
通过识别查询命中是有序的,可以加快速度。我们想要计算每次查询命中的平均值。我们首先创建一个变量来指示每个查询命中运行的结束
idx <- c(queryHits(olaps)[-1] != queryHits(olaps)[-length(olaps)], TRUE)
然后计算每次跑步结束时的累积分数,每次跑步的长度,以及跑步结束时和开始时累积分数之间的差值
scoreHits <- cumsum(scores[subjectHits(olaps)])[idx]
n <- diff(c(0L, seq_along(idx)[idx]))
xt <- diff(c(0L, scoreHits))
最后,平均值是
res2 <- xt / n
所有数据大约需要 0.6 秒,并且与 data.table 结果相同(尽管比?)
> identical(res1, res2)
[1] TRUE
均值对应的原始坐标为
start(q)[ queryHits(olaps)[idx] ]