我在优化一段R代码时遇到问题。下面的示例代码应该说明我的优化问题:
一些初始化和函数定义:
a <- c(10,20,30,40,50,60,70,80)
b <- c(“a”,”b”,”c”,”d”,”z”,”g”,”h”,”r”)
c <- c(1,2,3,4,5,6,7,8)
myframe <- data.frame(a,b,c)
values <- vector(length=columns)
solution <- matrix(nrow=nrow(myframe),ncol=columns+3)
myfunction <- function(frame,columns){
athing = 0
if(columns == 5){
athing = 100
}
else{
athing = 1000
}
value[colums+1] = athing
return(value)}
有问题的for循环如下所示:
columns = 6
for(i in 1:nrow(myframe){
values <- myfunction(as.matrix(myframe[i,]), columns)
values[columns+2] = i
values[columns+3] = myframe[i,3]
#more columns added with simple operations (i.e. sum)
solution <- rbind(solution,values)
#solution is a large matrix from outside the for-loop
}
问题似乎出在rbind
函数上我经常收到关于solution
大小的错误消息,过一段时间后,它似乎太大了(超过50MB)。我想用列表和lapply
和/或foreach替换这个循环和rbind
。我已经开始将myframe
转换为列表。
myframe_list <- lapply(seq_len(nrow(myframe)), function(i) myframe[i,])
虽然我尝试将这个非常好的介绍应用于并行处理,但我并没有真正做到这一点。
如何在不更改myfunction
的情况下重建for循环?显然,我对不同的解决方案持开放态度。。。
编辑:这个问题似乎直接来自R地狱的第二圈。有什么建议吗?
在这样的循环中使用rbind
是一种糟糕的做法,因为在每次迭代中,您都会放大solution
数据帧,然后将其复制到一个新对象,这是一个非常缓慢的过程,还会导致内存问题。一种方法是创建一个列表,其第i个组件将存储第i个循环迭代的输出。最后一步是调用该列表上的rbind(最后只调用一次)。这看起来像
my.list <- vector("list", nrow(myframe))
for(i in 1:nrow(myframe)){
# Call all necessary commands to create values
my.list[[i]] <- values
}
solution <- rbind(solution, do.call(rbind, my.list))
注释有点长,所以我把它放在这里:如果预先知道columns
:
myfunction <- function(frame){
athing = 0
if(columns == 5){
athing = 100
}
else{
athing = 1000
}
value[colums+1] = athing
return(value)}
apply(myframe, 2, myfunction)
如果columns
不是通过环境给出的,可以使用:
apply(myframe, 2, myfunction, columns)
和您原来的myfunction
定义。