找到一种有效的方法来计算两个表中间隔集之间的重叠次数?

时间:2014-09-25 20:58:55

标签: r data.table

注意:为方便起见,我使用上一篇文章中的示例数据集。

假设有两个数据集refmap。他们是:

ref <- data.table(space=rep('nI',3),t1=c(100,300,500),t2=c(150,400,600),id=letters[1:3])

map <- data.table(space=rep('nI',241),t1=seq(0,1200,by=5),t2=seq(5,1205,by=5),res=rnorm(241))
他们看起来像是:

> ref
   space t1  t2   id
1:    nI 100 150  a
2:    nI 300 400  b
3:    nI 500 600  c

> map
   space   t1   t2        res
1:    nI    0    5 -0.7082922
2:    nI    5   10  1.8251041
3:    nI   10   15  0.2076552
4:    nI   15   20  0.8047347
5:    nI   20   25  2.3388920
---                           
237:    nI 1180 1185  1.0229284
238:    nI 1185 1190 -0.3657815
239:    nI 1190 1195  0.3013489
240:    nI 1195 1200  1.2947271
241:    nI 1200 1205 -1.5050221

现在,我注意到在仍处于开发阶段的data.table包中,函数foverlaps将在ref中填充map中的相应行。 }。

setkey(ref,space,t1,t2)

foverlaps(map,ref,type="within",nomatch=0L)

给出:

   space t1  t2  id i.t1 i.t2         res
1:    nI 100 150  a  100  105 -0.85202726
2:    nI 100 150  a  105  110  0.79748876
3:    nI 100 150  a  110  115  1.49894097
4:    nI 100 150  a  115  120  0.47719957
5:    nI 100 150  a  120  125 -0.95767896
6:    nI 100 150  a  125  130 -0.51054673
7:    nI 100 150  a  130  135 -0.08478700
8:    nI 100 150  a  135  140 -0.69526566
9:    nI 100 150  a  140  145  2.14917623
10:    nI 100 150  a  145  150 -0.05348163
11:    nI 300 400  b  300  305  0.28834548
12:    nI 300 400  b  305  310  0.32449616
13:    nI 300 400  b  310  315  1.16107248
14:    nI 300 400  b  315  320  1.08550676
15:    nI 300 400  b  320  325  0.84640788
16:    nI 300 400  b  325  330 -2.15485447
17:    nI 300 400  b  330  335  1.59115714
18:    nI 300 400  b  335  340 -0.57588128
19:    nI 300 400  b  340  345  0.23957563
20:    nI 300 400  b  345  350 -0.60824259
21:    nI 300 400  b  350  355 -0.84828189
22:    nI 300 400  b  355  360 -0.43528701
23:    nI 300 400  b  360  365 -0.80026281
24:    nI 300 400  b  365  370 -0.62914234
25:    nI 300 400  b  370  375 -0.83485164
26:    nI 300 400  b  375  380  1.46922713
27:    nI 300 400  b  380  385 -0.53965310
28:    nI 300 400  b  385  390  0.98728765
29:    nI 300 400  b  390  395 -0.66328893
30:    nI 300 400  b  395  400 -0.08182384
31:    nI 500 600  c  500  505  0.72566100
32:    nI 500 600  c  505  510  2.27878366
33:    nI 500 600  c  510  515  0.72974139
34:    nI 500 600  c  515  520 -0.35358019
35:    nI 500 600  c  520  525 -1.20697646
36:    nI 500 600  c  525  530 -0.01719057
37:    nI 500 600  c  530  535  0.06686472
38:    nI 500 600  c  535  540 -0.40866088
39:    nI 500 600  c  540  545 -1.02697573
40:    nI 500 600  c  545  550  2.19822065
41:    nI 500 600  c  550  555  0.57075648
42:    nI 500 600  c  555  560 -0.52009726
43:    nI 500 600  c  560  565 -1.82999177
44:    nI 500 600  c  565  570  2.53776578
45:    nI 500 600  c  570  575  0.85626293
46:    nI 500 600  c  575  580 -0.34245708
47:    nI 500 600  c  580  585  1.21679869
48:    nI 500 600  c  585  590  1.87587020
49:    nI 500 600  c  590  595 -0.23325264
50:    nI 500 600  c  595  600  0.18845022
space  t1  t2 id i.t1 i.t2         res

运行data.table 1.9.3的开发版本,以下代码将帮助您运行它:

install.packages("devtools")
library(devtools)
dev_mode(on=T)

install_github("Rdatatable/data.table", build_vignettes=FALSE)

dev_mode(on=F)

我想做的是:

以上基本列出了时间间隔内包含的所有间隔。但是,我正在尝试按ref创建一个新列,计算 mapref的时间间隔内的行数。因此,我想要的表是:

> ref
   space t1  t2  id  count
1:    nI 100 150  a     10
2:    nI 300 400  b     20
3:    nI 500 600  c     20

每个map的每个时间间隔之间的ref行数落在{{1}}之间。虽然我理解一个非常基本的解决方案是只使用求和或计数函数来计算,是否有一个解决方案可以创建计数而无需先创建更大的填充数据集?我这样说是因为我的真实数据包含超过3亿次观测。任何建议都会有很大帮助!谢谢!

3 个答案:

答案 0 :(得分:5)

您可以使用which=TRUE参数来获取重叠位置,然后通过执行简单聚合来使用计数

ans = foverlaps(map, ref, type="within", nomatch=0L, which=TRUE)[, .N, by=yid]
#    yid  N
# 1:   1 10
# 2:   2 20
# 3:   3 20

然后在ref中重新开始。但我们应该提供一种更直接的方法来实现这一目标。

答案 1 :(得分:2)

你可以这样做:

count <- function(x, y) map[,sum(t1>=x & t2<=y)]
ref[, count:=mapply(x=t1, y=t2, count)]
ref

   space  t1  t2 id count
1:    nI 100 150  a    10
2:    nI 300 400  b    20
3:    nI 500 600  c    20

答案 2 :(得分:1)

为遗传数据开发的 Biocondcutor GenomicRanges软件包具有“空间”的概念。 (序列名称),空间内的坐标(整数范围定义为起始坐标和结束坐标的闭合间隔),以及元数据&#39;与每个范围关联的列。所以

library(GenomicRanges)
ref <- with(ref, GRanges(space, IRanges(t1, t2), id=id))
map <- with(map, GRanges(space, IRanges(t1, t2), res=rnorm(241)))

GenomicRanges支持许多基于范围的操作,包括

ref$count <- countOverlaps(ref, map)

要完成你感兴趣的事情(countOverlaps支持不同的重叠概念,所以默认(范围之间的任何重叠)可能不是你感兴趣的;一个范围是包含在内的&#39;它的开始和结束,但范围可以很容易地改变或缩小;这两者都可能意味着countOverlaps()的直接应用与你期望的不同。

要处理大量数据,通过打开与数据源的连接并读取连续的行,或通过连续行读取数据块(例如,大型数据的10M行)是很自然的。对数据库或任何文件格式进行基于范围的查询。

con <- open("my.csv")
while (nrow(map0 <- read.csv(con, nrows=10000000))) {
    map <- with(map0, GRanges(space, IRanges(t1, t2)))
    ref$count <- ref$count + countOverlaps(ref, map)
}
close(con)