以lapply / sapply访问前面的元素

时间:2015-07-24 12:14:18

标签: r lapply sapply

我正在尝试用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中访问以前的迭代结果?

2 个答案:

答案 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等于3y也是如此。表达式现在为3[3-1]。简化为3[2]。这是一个问题,因为向量3的第二个元素是什么?没有,它只有一个元素。因此返回NA。在循环的其余部分也会发生同样的效果。