在r中循环,直到值收敛并存储所有输出

时间:2014-04-23 21:26:09

标签: r loops while-loop

我想重复这个过程,除非在存储结果的某个时候满足条件。

这是一个简单的例子,我知道在循环中执行的循环次数:

# just example data
smpls <- rnorm(100,50,50)

ncycles <- 1000
outm <- matrix(nrow=ncycles, ncol = 1)

#重复n个周期的过程

for(i in 1:ncycles){    
outm[i]  <- mean(sample(smpls, 50))
}
# get average of outm
outm <- mean(sample(smpls, 50))

但我的情况不同,因为我不知道ncyles。我想继续采样,除非样本的方差或收敛非常低(我猜它是&#34;而#34;循环。例如,除非vsd在下列情况下小于1。

vsd <- NULL
outm <- mean(sample(smpls, 50))
while (vsd > 1){
    outm[i] <- mean(sample(smpls, 50))
    vsd <- sd(outm)
     }

我不知道我在这里设定的价值。帮助赞赏

编辑:

smpls <- rnorm(100,50,50)
iter <- 0
# maximum iteration 
itermax <- 1000 
outm <- rep(NA, itermax)
vsd <- 2
while((vsd > 1 ) && (iter < itermax)) {
     outm[iter] <- mean(sample(smpls, 50))
     vsd <- sd(outm)
     iter <- iter+1
     }
Error in while ((vsd > 1) && (iter < itermax)) { : 
  missing value where TRUE/FALSE needed

当它达到收敛时停止的主要想法是节省时间。虽然上面只有平均函数的例子很快,但我的原始函数需要很长时间来进行迭代,我想在它收敛时停止它。

3 个答案:

答案 0 :(得分:2)

代码中存在两个问题:

1)你需要sd(...,na.rm = TRUE)

2)你需要确保sd的outm中至少有两个数字(outm,na.rm = TRUE)!= NA

顺便说一句,鉴于你指定的sd,我认为你不需要超过几十次迭代

sim <- function() {
  smpls <- rnorm(100,50,5)
  itermax <- 1000
  outm <- rep(NA, itermax)
  outm[1] <- mean(sample(smpls, 50))
  iter <- 1
  vsd <- 2
  while((vsd > 1 ) && (iter < itermax)) {
       iter <- iter+1
       outm[iter] <- mean(sample(smpls, 50))
       vsd <- sd(outm, na.rm = TRUE)
       }

  iter
  }

set.seed(666)
iters <- replicate(100000, sim() )
range(iters)  # c(2, 11)

干杯。

答案 1 :(得分:1)

这是一个解决方案:

数据

set.seed(123) # so that you can replicate what I did 
smpls <- rnorm(100,50,50)

我认为你需要一些初始化周期(最小迭代次数),这样你就会得到错误的收敛,因为你的样本数量很少。所以运行一些样品 - 比如说miniter。你还需要一个最大的迭代,这样你的循环就不会变得狂野 - 比如说maxiter。

 meanconverge <- function (data, miniter, maxiter, tolerance){ 
      outm <- rep(NA, maxiter) 
     for(i in 1:miniter){    
     outm[i]  <- mean(sample(smpls, 50))
     }
     # sd of initial cycles 
    vsd <- sd(outm, na.rm = TRUE)
     if(vsd > tolerance) {
                   iter <- miniter+1
                   sdout <- rep(NA, maxiter)
                   while((vsd > tolerance ) && (iter < maxiter)) {
                     iter <- iter + 1
                     outm[iter] <- mean(sample(smpls, 50))
                     vsd <- sd(outm, na.rm = TRUE)
                     sdout[iter] <- vsd             
       } 
      out <- list(outm, sdout)
      return(out)
      } else {
      return(outm)
      }
      }

 out <- meanconverge  (data = smpls, miniter = 50, maxiter = 100000, tolerance = 3)
 plot(unlist(out[2]), pch = ".", col = "red") 

enter image description here

 plot(unlist(out[1]), pch = ".", col = "red")

enter image description here

答案 2 :(得分:0)

检查收敛是一件棘手的事情。一个很好的入门方法是在计算时查看值的变化情况。趋同就是任意接近边界;以编程方式,您必须选择“任意”的含义。您还需要决定如何衡量收敛。

为了说明,假设我想知道我的符合条件的估计是否真的彼此接近。我可能有类似的东西:

# inside my function or method that performs this convergence feat
while (while_condition && i < itermax)) {

    outcome[i] <- some_complicated_foo(bar)

    if ( abs(outcomes[i-1] - outcomes[i]) <= tolerance ) {
       while_condition <- FALSE # i.e. STOP LOOPING
       return outcomes
    } 

    else {continue}

}

tolerance是你对任意亲密度的定义。现在,这对你的指甲来说似乎是一把锤子吗?那么,如果你收敛到错误的答案会发生什么?你怎么知道的?这件事甚至会收敛吗?这些问题的诀窍是对您正在分析的函数或数据生成过程进行切割器猜测。但是,只要合理,拥有最大迭代边界肯定会减轻一些计算时间。知道你是否正确的真正方法是使用测试(如统计测试或单元测试)来查看是否存在任何“垃圾垃圾”或者获得与您期望的不同的东西。一个众所周知的答案。

查看优化算法并了解它们是如何做到的。请参阅?optim或其他一些优化包,了解专家如何做到这一点。