假设我有两个向量,A和B. A有15个变量,B有28个变量。
A = c(13,14,29,31,32,39,42,51,59,61,68,91,102,109,120)
B = c(26,26,28,29,30,30,33,38,41,42,45,46,47,47,49,49,80,81,86,86,90,90,92,100,101,105,105,107)
我想要一个14乘27的矩阵Z,其中如果(B_j,B_ {j + 1}]与(A_i,A_ {i + 1}]重叠,则i by j条目为1。
例如,Z的(3,4)条目将是1,因为(29,31]和(29,30)重叠,30作为公共数。是否有快速计算方法?
我有以下代码:
Z = matrix(0, length(A)-1, length(B)-1)
for (i in 1:(length(A)-1)){
nn = which(B > A[i] & B <= A[(i+1)])
if (length(nn)>0){
Z[i,(nn-1)] = 1}}
它运作良好,但我的A和B矢量通常包含30,000多个元素,而且速度非常慢。制作矩阵Z甚至需要不必要的长时间。任何人都可以帮忙吗?
理想情况下,有一个矢量化的解决方案可以解决这个问题,也可以从包中编写一个很好的函数来解决这个问题。
答案 0 :(得分:3)
这是一个使用矩阵乘法的选项。正如所评论的那样,矩阵可能变得很大,你必须看看速度提升是否值得:
res1 <- outer(A, B, FUN = function(A, B){B > A})
res2 <- outer(A, B, FUN = function(A, B){B <= A})
dim(res1); dim(res2)
res3 <- (res1[-nrow(res1),] + res2[-1,]) == 2
image(res3)
dim(res3)
op <- par(mfcol=c(1,2))
image(Z, main="Z")
image(res3, main="res3")
par(op)
答案 1 :(得分:2)
如果关闭时间间隔[B_j,B_{j+1}]
和[A_i, A_{i+1}]
也适合您,您可以使用
A <- as.integer(c(13,14,29,31,32,39,42,51,59,61,68,91,102,109,120))
B <- as.integer(c(26,26,28,29,30,30,33,38,41,42,45,46,47,47,49,49,80,81,86,86,90,90,92,100,101,105,105,107))
DT_A <- data.table(A0 = A, A1 = shift(A, type = "lead"), key=c("A0", "A1"))[-length(A)]
DT_B <- data.table(B0 = B, B1 = shift(B, type = "lead"), key=c("B0", "B1"))[-length(B)]
ind_true <- foverlaps(DT_A, DT_B, type="any", mult="all", which=TRUE)[!is.na(yid)]
mat <- matrix(0, length(A)-1, length(B)-1)
mat[ind_true$xid, ind_true$yid] = 1
答案 2 :(得分:1)
这个答案使用矩阵索引并依赖于expand.grid
,尽管它的实现速度要快得多。你滞后你的向量来创建A和B的矩阵,然后用一个做简单布尔检查的函数,我们可以用扩展网格索引到矩阵。然后它返回一个矩阵。
overlap = function(id,x1,x2){
idA = id[,1]
idB = id[,2]
o = (x1[idA,1] >= x2[idB,1] & x1[idA,1] <= x2[idB,2]) | (x1[idA,2] >= x2[idB,1] & x1[idA,2] <= x2[idB,2]) |
(x1[idA,1] <= x2[idB,1] & x1[idA,2] >= x2[idB,1]) | (x1[idA,1] <= x2[idB,2] & x1[idA,2] >= x2[idB,2])
matrix(o,nrow=nrow(x1))
}
A = c(13,14,29,31,32,39,42,51,59,61,68,91,102,109,120)
nA = cbind(lag(A),A)[-1,]
B = c(26,26,28,29,30,30,33,38,41,42,45,46,47,47,49,49,80,81,86,86,90,90,92,100,101,105,105,107)
nB = cbind(lag(B),B)[-1,]
expand.grid.jc <- function(seq1,seq2) {
cbind(Var1 = rep.int(seq1, length(seq2)),
Var2 = rep.int(seq2, rep.int(length(seq1),length(seq2))))
}
ids = expand.grid.jc(1:nrow(nA),1:nrow(nB))
overlap(ids,nA,nB)