在R编程中使用具有不同长度的成对迭代的双循环的替代方案

时间:2017-04-20 18:34:06

标签: r loops vectorization lapply mapply

我试图评估列表中一系列长度为10的非冗余元素对之间的交集(例如" abc"),对于每个元素,它包含两个长度为20的整数向量,并为具有超过一定数量(例如2)的交叉点生成对索引的向量,如下所示:

set.seed(42)
abc <- replicate(10, list(sample(1:100, 20), sample(1:100, 20)), simplify=F)

edges <- c()
for (i in 1:(length(abc)-1)) {
  for (j in (i+1):length(abc)) {
    if (length(intersect(abc[[i]][[1]], abc[[j]][[1]])) >= 2 & length(intersect(abc[[i]][[2]], abc[[j]][[2]])) >= 2) {
      edges <- c(edges, c(i,j))
    }
  }
}

我只是想知道是否有其他方法可以产生相同的结果,但是效率更高更快?使用具有合理大小的列表的循环似乎没问题,但是当涉及到更大的列表时,它需要比预期更多的时间。我试图使用&#39; lapply&#39;或其他类似的功能,但使用那些&#39; lapply&#39;对于单循环来说,类型函数似乎很简单,但对于具有不同循环迭代次数的双循环,我很难找到一个好的解决方案。提前谢谢!

1 个答案:

答案 0 :(得分:0)

您可以使用combs生成可以迭代的索引:

set.seed(47)

abc <- replicate(10, list(sample(1:100, 20), sample(1:100, 20)), simplify=F)

combs <- combn(length(abc), 2)

i <- apply(combs, 2, function(x){
    length(intersect(abc[[x[1]]][[1]], abc[[x[2]]][[1]])) >= 2 &
    length(intersect(abc[[x[1]]][[2]], abc[[x[2]]][[2]])) >= 2
})

combs[,i]
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
#> [1,]    1    1    1    1    1    1    1    1    1     2     2     2     2
#> [2,]    2    3    4    5    6    7    8    9   10     3     4     5     6
#>      [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22] [,23] [,24]
#> [1,]     2     2     2     3     3     3     3     3     4     4     4
#> [2,]     7     8    10     4     6     8     9    10     5     6     7
#>      [,25] [,26] [,27] [,28] [,29] [,30] [,31] [,32] [,33] [,34] [,35]
#> [1,]     4     4     4     5     5     5     5     5     6     6     6
#> [2,]     8     9    10     6     7     8     9    10     7     8     9
#>      [,36] [,37] [,38] [,39] [,40] [,41]
#> [1,]     6     7     7     7     8     9
#> [2,]    10     8     9    10    10    10

但请注意,因为组合快速变大,而10个元素(choose(10, 2) = 45种组合)的速度很快,对于10,000个元素的不可想象的列表,检查choose(10000, 2) = 49,995,000与两个子元素的组合每个都会占用更多的内存和时间。