使用tryCatch()但遇到错误/警告时不要覆盖对象

时间:2016-01-21 00:11:34

标签: r for-loop try-catch

我希望在for循环内迭代拟合merMod模型并存储结果。当我遇到错误时,我不希望lmer()对象(来自merMod模型的输出)覆盖上一次迭代中的# install.packages(c("lme4", "dplyr", "ggplot2"), dependencies = TRUE) library("lme4") library("dplyr") library("ggplot2") predList <- list() j <- 1 for(i in 2:9){ tr <- sleepstudy %>% filter(Days < i) pr <- sleepstudy %>% filter(Days == i) fm <- tryCatch({lmer(Reaction ~ Days + (1|Subject), data=sleepstudy)}, warning = function(w) {#Code to move along to `predict` without overwriting `fm`}, error = function(e) {#Code to move along to `predict` without overwriting `fm`}) #predict the Reaction pr$prRe <- predict(fm, pr) predList[[j]] <- pr j = j + 1 } pred <- bind_rows(predList) %>% arrange(Subject, Days) ggplot(data=pred, aes(Reaction, prRe)) + geom_point() 对象。例如:

i=4

这段代码实际上没有问题。但是,让我们说lmer()时,我从fm收到错误。发生这种情况时,我不想用错误消息替换fm。相反,我只想保留i=3(从predict开始的模型输出),然后移到lmer()之后的lmer()语句。我怎么能这样做?

特殊情况可能是第一次迭代失败时。我们不用担心。假设循环的第一次迭代总是成功地适合# install.packages(c("lme4", "dplyr", "ggplot2"), dependencies = TRUE) library("lme4") library("dplyr") library("ggplot2") predList <- list() j <- 1 for(i in 2:9){ tr <- sleepstudy %>% filter(Days < i) pr <- sleepstudy %>% filter(Days == i) fm <- tryCatch({lmer(Reaction ~ Days + (1|Subject), data=sleepstudy)}, warning = function(w) {message(w)}, error = function(e) {message(e)}) #If model did not fail, predict as usual and store fm in fm0. If model did fail, use fm0 from previous iteration for prediction if(is.null(fm)){ pr$prRe <- predict(fm0, pr) } else {fm0 <- fm pr$prRe <- predict(fm, pr) } predList[[j]] <- pr j = j + 1 } 模型。

一种解决方案可能是:

tryCatch()

但这有点冗长。有什么简单的我可以放在fm函数中,只是不覆盖{{1}}并在模型失败时移动到下一个语句?

1 个答案:

答案 0 :(得分:1)

我可以想到一个解决方案,首先如果你不想覆盖fm并且只是转到下一个声明:

使用一些初始模型fm0初始化fm:

fm <- fm0

然后运行你的for循环:

for ( i in 2:9 ){
    fm <- tryCatch({lmer(Reaction ~ Days + (1|Subject), data=sleepstudy)},
    error = function(e){return(fm)}) #return previous value of fm if error

    # do something else

}

但是,我不明白为什么你有两个索引ij。请注意,j以值1开头,i以值2开头。在每次迭代中,由于您的最后一行j = j + 1,两个值都会递增1,因此在下一次迭代中j为2,i为3,依此类推。所以你的代码是相同的

for (j in 1:8){
   i <- j+1
   #your code here
}

这看起来更好imho。