R - 矢量化嵌套for循环?

时间:2015-02-28 20:46:14

标签: r vectorization nested-loops

我有2个大数据帧(头部(CON_FRAs)和头部(插头),如下所示),我想比较和修改的值。我来自python背景,因此创建了这个嵌套for循环,实现了我的目标,即在CON_FRAs $ V4和CON_FRAs $ V5之间找到indels $ V4的值,并在indels $ CON和CON_FRAs $ V6中加1,只是非常慢慢地(运行1小时)。

有人可以帮我矢量化这段代码吗?

在旁注中,我也意识到我不应该在嵌套循环中要求相同的if条件两次,但是当我在R中编程并且无法使R接受2个动作时,我发现许多东西不直观if statement。

CON_FRAs

V1        V2        V3        V4        V5 V6
1  1  57859401  58018691  57859401  58018691  0
2  1  97522550  97892513  97522550  97892513  0
3  1 214173802 224638502 214173802 224638502  0
4  1 184035608 184239812 184035608 184239812  0
5  2 140988941 141140259 390239564 390390882  0
6  2 169205756 170181166 418456379 419431789  0

插入缺失

V1        V2        V3         V4         V5  V6     V7  V8            V9 V10 mut_type CON BIG FUN MRA LET recomb
1  6  96651182  96651183 57859401 57859402  AA      T CLL 001-0002-03TD  NA  COMPLEX   0   0   0   0   0      0
2 10  38406960  38406961 1718780121 1718780122  AG      - CLL 003-0005-09TD  NA      DEL   0   0   0   0   0      0
3  2  87017743  87017744  336268366  336268367   C     CT CLL 003-0005-09TD  NA  COMPLEX   0   0   0   0   0      0
4 20   5538748   5538750 2724112091 2724112093 CCC      A CLL    012-02-1TD  NA  COMPLEX   0   0   0   0   0      0
5  9 139390648 139390649 1678550376 1678550377  AG      - CLL    012-02-1TD  NA      DEL   0   0   0   0   0      0
6 10  10498176  10498180 1690871337 1690871341   - GAAAAA CLL           125  NA      INS   0   0   0   0   0      0

我的嵌套循环

for(j in 1:length(indels$V4)){
   for(i in 1:length(CON_FRAs$V4)){
     if(CON_FRAs$V4[i] < indels$V4[j] & indels$V4[j] < CON_FRAs$V5[i])
       indels$CON[j] = 1
     if(CON_FRAs$V4[i] < indels$V4[j] & indels$V4[j] < CON_FRAs$V5[i])
       CON_FRAs$V6[i] = CON_FRAs$V6[i] + 1}}

更新:我已经设法通过将一个矢量化命令放在单个循环中的一半方法来改进性能,从而否定嵌套循环的指数增加,但仍然需要两个循环(见下文)。这将运行时间减少到不到2分钟。这将是我现在必须做的,因为它足够快,如果有人能提供完全矢量化的解决方案,仍然会感兴趣

for(j in 1:length(indels$V4)){
  inc(CON_FRAs$V6[CON_FRAs$V4 < indels$V4[j] & indels$V4[j] < CON_FRAs$V5]) <- 1}

for(i in 1:length(CON_FRAs$V6)){
  indels$CON[CON_FRAs$V4[i] < indels$V4 & indels$V4 < CON_FRAs$V5[i]] <- 1}

1 个答案:

答案 0 :(得分:1)

就你的旁注问题而言,这应解决它:

for(j in 1:length(indels$V4)){
   for(i in 1:length(CON_FRAs$V4)){
     if(CON_FRAs$V4[i] < indels$V4[j] & indels$V4[j] < CON_FRAs$V5[i]) {
       indels$CON[j] = 1
       CON_FRAs$V6[i] = CON_FRAs$V6[i] + 1}
                                 } }

我认为从“矢量化”视角考虑这是两个不同的问题,其中可能使用“外部”为逻辑测试生成矩阵。它会在“i”值的“V6”值的累积上完成一个colSums,但对于“indel $ CON”列,我认为它可能是“any”的结果(使用apply或者“j”中的colMax来自非基础包)

outer(1:nrow(indels), 
      1:nrow(CON_FRAs),
       function(X,Y) {CON_FRAs$V4[X] < indels$V4[Y] & 
                      indels$V4[Y] < CON_FRAs$V5[X]} )

      [,1]  [,2]  [,3]  [,4]  [,5]  [,6]
[1,] FALSE FALSE FALSE FALSE FALSE FALSE
[2,] FALSE FALSE FALSE FALSE FALSE FALSE
[3,] FALSE FALSE FALSE FALSE FALSE FALSE
[4,] FALSE FALSE FALSE FALSE FALSE FALSE
[5,] FALSE FALSE FALSE FALSE FALSE FALSE
[6,] FALSE FALSE FALSE FALSE FALSE FALSE

买者。我之前的努力得到了不同的结果。修复逻辑表达式中的索引会给我与代码相同的(微不足道的)结果,但是如果你输入一个更好的测试用例,我们可以更好地比较结果。