R - 比较两个数据集时如何避免循环?

时间:2014-11-16 23:50:45

标签: r loops vectorization

版本以简化问题

我有两个矩阵:

  • mat1:nrow = 100 000; NcoI位= 5
  • mat2:nrow = 500 000; NcoI位= 5

预期结果

计算mat1的每一行与mat2的每一行之间的相似数字的数量:

提案

   Intersection <- function(matrix1, matrix2){
        Intersection = matrix(nrow=nrow(matrix1), ncol=ncol(matrix2)) 
          for(i in 1:nrow(matrix3)) {
            for(j in 1:ncol(matrix3)) {
            Intersection[i,j] = length(intersect(matrix1[i,], matrix2[j,])
           } 
         }   
    return(Intersection) }

问题:

如何对此函数进行向量化以避免循环

数据样本

以下是试验解决方案的数据样本:

  

dput(矩阵1)   结构(c(1L,20L,2L,1L,7L,2L,22L,12L,2L,27L,3L,35L,   16L,3L,32L,4L,37L,35L,17L,33L,5L,38L,46L,27L,49L),. Dim = c(5L,   5L))

     

dput(矩阵2)   结构(c(1,14,7,1,7,2,22,12,2,27,7,35,16,3,32,   14,39,35,17,32,17,38,46,20,49),. Dim = c(5L,5L))

1 个答案:

答案 0 :(得分:2)

提高处理效率的方法不是抛弃循环而是检查循环的内部逻辑。在这种情况下,您似乎希望使用TARGET的列-i中的交叉元素的数量,mat的列-j作为偏移量来选择“IF_n”列中的元素并放置第(5 + i)行和第j列中的该项。当以这种方式描述问题时,我们应该能够摆脱所有ifelse语句。 (我经常发现花时间用最清晰的自然语言重述问题是提高效率的关键。)在获得0结果索引第五列时会涉及一些模数算法。

在询问df $ TARGET [i]与mat-column的交集长度时,我也遇到了问题。 df $ TARGET [i]只能是单个数字,因为您使用向量索引而不是矩阵索引。 (df $ TARGET是一个矩阵,所以它应该是df $ TARGET [,i])

这是我的反建议。我认为它更符合预期的结果,并且可能至少快5倍,因为你可以完全消除所有ifelse文件夹。)

BDfunc <- function(df, mat){
  for  (i in 1:nrow(df)) {   # print(i)  (use for debugging)
    for (j in 1:ncol(mat)){  # print(j)
     mat[5+i, j]<- df[i , 2 + (
      (length(intersect(df$TARGET[,i], mat[,j])) ) %% 5 )]   }
  }
  return(mat)
}   
 mat <- BDfunc(df, mat)

> mat
          [,1]      [,2]      [,3]      [,4]      [,5]
 [1,] 1.000000 20.000000  2.000000  1.000000  7.000000
 [2,] 2.000000 22.000000 12.000000  2.000000 27.000000
 [3,] 3.000000 35.000000 16.000000  3.000000 32.000000
 [4,] 4.000000 37.000000 35.000000 17.000000 33.000000
 [5,] 5.000000 38.000000 46.000000 27.000000 49.000000
 [6,] 5.855105  2.216690  7.458434  3.120932  2.216690
 [7,] 6.381849  6.381849  6.630405  6.381849  6.630405
 [8,] 2.464372  2.464372  2.464372  5.993037  5.993037
 [9,] 1.614552  1.614552  1.614552  5.507400  1.614552
[10,] 2.088811  2.088811  2.088811  2.088811  5.974585