【问题标题】:R: Speed up for loopR:加速循环
【发布时间】:2014-04-04 11:46:17
【问题描述】:

这是我的 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

【问题讨论】:

  • 如果你举一个dat数据的例子,以及这段代码打算做什么的简要描述,会更容易回答。
  • @Maxim.K:查看我对dat 文件的编辑。此代码根据等位基因频率数据计算修改后的罗杰斯遗传距离。

标签: r performance for-loop


【解决方案1】:

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

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

【讨论】:

  • 您可能需要添加 d
  • @sgibb:是的,你是对的。非常感谢。你让我的生活变得简单。
  • @ramesh:如果这解决了您的问题,请您接受答案。
  • 我觉得dat[, -c(1, 2)]应该换位?
  • @MartinMorgan:谢谢!
【解决方案2】:

你可以做的最大的事情来加速循环是在循环之前预先分配向量和矩阵。然后,不使用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&lt;-(1/(2*length(unique(dat[,1])))))都应该移出循环。否则,您只是一遍又一遍地重新计算相同的值,这会对性能产生负面影响。

循环的关键是避免rbind()cbind(),通过在循环之前预分配向量和矩阵将提供很多的性能提升。

【讨论】:

  • 他也可以将row1&lt;-(1/(2*length(unique(dat[,1]))))移出循环。
【解决方案3】:

虽然类似的功能已经存在,但我尝试了自己的方式。
我删除了一个完整的for 循环、rbindcbind
现在只需 124 秒即可写入 1014 X 1014 矩阵,而只需 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
  }

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 2023-03-07
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多