这是我的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
答案 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
循环,rbind
和cbind
。
现在,仅用一个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
}
希望这段代码仍然可以改进。