R:加速循环

时间:2014-04-04 11:46:18

标签: r performance for-loop

这是我的R脚本,有三个嵌套的for循环。在2000轮for循环中完成1次需要2分钟以上。如何加速这个?

col<-NULL
row<-NULL
rep<-ncol(dat)-2
dist<-NULL
c1=3
for (i in 1:rep){
  c2=3
  for(j in 1:rep){
    r=1
    for (k in 1:nrow(dat)){
      p<-(dat[r,c1]-dat[r,c2])^2
      row<-rbind(row, p)
      r=r+1
    }
    row<-sqrt(sum(row))
    row1<-(1/(2*length(unique(dat[,1]))))*row
    col<-cbind(col, row1)
    c2=c2+1
    row<-NULL
  }
  dist<-rbind(dist,col)
  col<-NULL
  c1=c1+1
}

编辑:

> head(dat)
  mark alle G1 G2 G3 G4 G5 G6 G7 G8 G9 G10 G11 G12 G13 G14 G15 G16 G17 G18 G19 G20 G21 G22 G23 G24
1   M1  228  1  1  1  1  1  1  1  1  1   1   1   1   1   1   1   1   1   1   1   1 0.0 0.5   0   0
2   M1  234  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0 0.5 0.5   1   1
3   M1  232  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0 0.0 0.0   0   0
4   M1  240  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0 0.0 0.0   0   0
5   M1  230  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0 0.5 0.0   0   0
6   M1  238  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0 0.0 0.0   0   0

3 个答案:

答案 0 :(得分:4)

我不知道修改罗杰斯遗传距离,但它看起来像欧几里德距离乘以1/(2*length(unique(dat$mark)))

f <- 1/(2*length(unique(dat$mark)))
d <- f*dist(t(dat[, -c(1, 2)]), method="euclidean")

答案 1 :(得分:3)

加速循环可以做的最重要的事情是在循环之前预先分配向量和矩阵。然后,不是使用cbind()rbind(),而是将结果添加到矢量/矩阵中,如下所示:

# Was: row<-rbind(row, p)
row[k] <- p

# Was: col<-cbind(col, row1)
col[j] <- row1

# Was: dist<-rbind(dist,col)
dist[i, ] <- col

之后,您可以探索向量化操作的方法,或者更好的是,查看是否已存在执行此任务的函数(或者如果任务基于存在函数的事物)。此外,任何不依赖于循环的东西(例如row1<-(1/(2*length(unique(dat[,1])))))都应该移出循环。否则,您只是重复计算相同的值,从而对性能产生负面影响。

带循环的键通过在循环之前预先分配向量和矩阵来避免rbind()cbind(),从而提供 lot 的性能提升。

答案 2 :(得分:1)

虽然类似的功能已经存在,但我尝试了自己的方式。
我删除了一个完整的for循环,rbindcbind
现在,仅用一个1014 X 1014矩阵(意味着1 X 1014),仅需124秒即可在2分钟内写入1014 X 1014矩阵(意味着1 X 1014)。

dat<-read.table("alreq1.txt", sep="\t",header=T)
col<-NULL
row<-NULL
rep<-ncol(dat)-2
dist<-NULL
dist<- data.frame(matrix(NA, nrow = rep, ncol = rep))
m<-1/sqrt(2*length(unique(dat[,1])))
c1=3
for (i in 1:rep){
  c2=3
  for(j in 1:rep){
      p<-na.omit(dat[,c1]-dat[,c2])^2
      row<-sum(p)
      row<-sqrt(row)*m
      col[j] <- row
      c2=c2+1
      row<-NULL
      p<-NULL
  }
  dist[i,] <- col
  c1=c1+1
  col<-NULL
  }

希望这段代码仍然可以改进。