R中循环的性能问题

时间:2013-09-22 05:48:11

标签: r performance for-loop matrix distance

我有两个矩阵A和B.两个都包含一个名字列表。问题是基于相似性度量。我找到A元素与B(整个矩阵)的最小距离。如果汉明距离更大如果不是3,那么数据将被添加到矩阵B中,否则不会。那么让我举个例子

 A<-c("cvombiflam","combiflam")
 A<-as.matrix(A)

 B<-c("windfall","computer","baseball")
 B<-as.matrix(B)

现在A1将搜索B并找到与汉明距离最近的B成员。最接近的是B2。它会找到与B [2]的距离。由于最近的距离大于3,因此cvomiflam将被添加到B.现在B将是

 B<-c("windfall",
      "computer",
      "baseball",
      "cvombiflam")

现在A(“combiflam”)的第二个元素将搜索B.最接近的是B(cvombiflam)的第四个元素,距离为1.因此,不会在B中添加combiflam。我想更新最终的B列表

我写的代码是:

 for(i in 1:length(A))
 {    
      d<-min(stringdistmatrix(A[i],B)
      if(d>3)
      {            
           B<-rbind(B,A[i])
      }
 }   

现在我的A矩阵大约为140,000,B为200,000。代码工作正常但运行时间很长。请告诉我一个更快的方法。

2 个答案:

答案 0 :(得分:1)

您可以只存储和更新BTRUE的向量,而不是一遍又一遍地增长FALSE,这可能会导致内存空间变得非常昂贵A的元素应添加到B或不添加。然后,仅在最后,将这些选定的元素追加到B

另外需要注意的是,当你只需要向量时,你在任何地方都使用矩阵。我为你修好了。

A <- as.vector(A)
B <- as.vector(B)

add.A <- rep(FALSE, length(A))

for(i in 1:length(A)) {
  if (i %% 1000L == 0L) cat(sprintf("%.2f percent completed", 100 * i / length(A)))
  d.B <- stringdist(A[i], B)
  d.A <- stringdist(A[i], A[add.A])
  d <- min(c(d.B, d.A))
  if (d > 3) {            
    add.A[i] <- TRUE
  }
}

B <- c(B, A[add.A])

正在解决的问题是,您的问题规模仍然很大。要计算很多距离(至少length(A) * length(B)),这将花费很多时间。我在循环中添加了一个cat,让您了解运行时需要多长时间。请试一试并评论它的速度有多慢或多快。

此外,如果AB有共同的项目,您最初可以通过以下方式减少问题维度:

A <- unique(A)
B <- unique(B)
A <- setdiff(A, B)

答案 1 :(得分:0)

您的代码建议您迭代地增长对象BB = rbind(B, A[i])。由于B的内存大小要求不断增长,因此速度非常慢。不断延长B内存需要很长时间,导致循环变得非常慢。你可以做一些事来解决这个问题:

  • 在循环之前将B预分配到正确的大小并将其填入循环中。
  • 使用apply样式循环,最后使用rbind

    list_of_results = lapply(A, stringdistmatrix, b = B)
    big_data_frame = do.call('rbind', list_of_results)
    

加速计算的其他选项:

  • 使用多个核心,请参阅ncores的{​​{1}}参数。
  • 尝试不同的距离度量(stringdistmatrix参数),看看是否会产生影响。