可怕的标题问题,但这是我想要解决的问题。对于表1,我想添加“BETWEEN”列,以验证表2中相应“BIN”的“POSITION”是否介于“START”和“STOP”值之间。
表1 。 BIN的名称(字符)和POSITION(数字)中的位置:
BIN POSITION
1 12
1 52
1 86
7 6
7 22
X 112
X 139
MT 3
MT 26
表2 :BIN名称(字符)以及START和STOP位置(数字)
BIN START STOP
1 2 64
1 90 110
7 20 100
7 105 200
X 1 5
MT 1 1000
和期望的结果-表1中带有“BETWEEN”:
CHROM POSITION BETWEEN
1 12 TRUE
1 52 TRUE
1 86 FALSE
7 6 FALSE
7 22 TRUE
X 112 FALSE
X 139 FALSE
MT 3 TRUE
MT 26 TRUE
我的表1大约有4,000,000行,表2大约有500,000行,我想到的一切都很慢。
作为较大表的示例,请使用以下命令:
positions <- seq(1,100000,10)
bins <- c("A","B","C","D","E","F","G","H","I","J")
tab1 <- data.table(bin = rep(bins,1,each=length(positions)), pos = rep(positions,10))
tab2 <- data.table(bin = rep(bins,1,each=2000), start = seq(5,100000,50), stop = start+25)
所需的输出将是:
tab1
bin pos between
1: A 1 FALSE
2: A 11 TRUE
3: A 21 TRUE
4: A 31 FALSE
5: A 41 FALSE
最佳答案
以下方法要求对于给定的垃圾箱,垃圾箱是互斥的。 (例如,您不能使bin A的边界为1-5,而另一个bin A的边界为4-8。)此外,我对示例进行了一些修改。
positions <- seq(1,100000,10)
bins <- c("A","B","C","D","E","F","G","H","I","J")
tab1 <- data.table(bin = rep(bins,1,each=length(positions)), pos = rep(positions,10))
setkey(tab1,"bin","pos")
tab2 <- data.table(bin = rep(bins,1,each=2000), start = seq(5,100000,50))
tab2[, end := start+25]
tab2[,pos:=start]
setkey(tab2,"bin","pos")
x<-tab2[tab1, roll=TRUE, nomatch=0]
tab2[,pos:=end]
setkey(tab2,"bin","pos")
y<-tab2[tab1, roll=-Inf, nomatch=0]
setkey(x,"bin","pos","start")
setkey(y,"bin","pos","start")
inBin<-x[y,nomatch=0]
inBin[, between:=TRUE]
setkey(tab1,"bin","pos")
setkey(inBin,"bin","pos")
result<-inBin[,list(bin,pos,between)][tab1]
result[is.na(between), between:=FALSE]
我现在没有时间深入解释我的解决方案。相反,我将采取便宜的方法,并请您研究data.table的
roll
参数。上面的基本方法是,我要加入tab1和tab2,将pos向前滚动到最近的结束边界。然后,我加入tab1和tab2,将pos向后滚动到最近的起始边界。然后,我对这两个集合进行内部联接,使我在tab1中的所有行都落在bin的范围内。从那时起,这只是艰巨的工作。关于r - 用R数据检查一个表(X)中的值是否在另一表(Y)中两列的值之间。,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24878028/