我正在尝试用for
函数替换sapply
循环。在循环内部我做了一些优化,因此需要为下一个循环进行一次优化的结果。
我想出了如何使用sapply
来运行优化,但问题是我需要从sapply
中访问以前的结果。
以下只是我想要实现的一个随机例子。
sapply(1:4, function(y){
r<-y
if(y!=1){z<-r[y-1]}
else{z<-9}
return(z)
})
[1,] 9 2 NA NA
我期望得到的是:
[1,] 9 1 2 3
我做错了什么?或者有没有办法在sapply
中访问以前的迭代结果?
答案 0 :(得分:13)
这是一个可能更接近OP用例的例子:
f = function(x) x^2
g = function(x) abs(x)+rnorm(1)
yvec = 1:4
这是@Andrie提到的Reduce
方法:
set.seed(1)
Reduce(function(z,y) if (is.na(z)) f(y) else g(z), yvec,init=NA_real_,accumulate=TRUE)[-1]
# [1] 1.0000000 0.3735462 0.5571895 -0.2784391
这是一个每个人都会使用的常识循环(@digEmAll提到):
set.seed(1)
res <- rep(NA_real_,length(yvec))
for (i in seq_along(yvec)) res[i] = if (i==1) f(yvec[i]) else g(res[i-1])
res
# [1] 1.0000000 0.3735462 0.5571895 -0.2784391
结果是一样的,所以,Reduce
只是隐藏了循环,正如@Roland所声称的那样。
答案 1 :(得分:5)
您无法使用apply系列函数访问以前的结果。它们是for
循环的包装器,因此没有理由明确地避免循环,如果这就是你所追求的。
对于你的问题“我做错了什么?”。有了你的功能:
sapply(1:4, function(y){
r<-y
if(y!=1){z<-r[y-1]}
else{z<-9}
return(z)
})
在表达式r[y-1]
中,NA是在前两个循环之后产生的。
当1
通过时,它会转到else
语句,z
会被分配9
。当2
通过时,它会转到表达式r[y-1]
。在该迭代中,r
等于2
,因此y
。因此它等同于2[2-1]
,简化为2[1]
。这可以理解为“向量的第一个元素2
。答案为2
。
在下一轮中,r
等于3
,y
也是如此。表达式现在为3[3-1]
。简化为3[2]
。这是一个问题,因为向量3
的第二个元素是什么?没有,它只有一个元素。因此返回NA
。在循环的其余部分也会发生同样的效果。