2016-01-21 86 views
0

我想在for循環內迭代地擬合lmer()模型並存儲結果。當我遇到錯誤時,我不希望merMod對象(lmer()模型的輸出)覆蓋上一次迭代中的merMod對象。例如:使用tryCatch()但在遇到錯誤/警告時不覆蓋對象

# 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開始的模型輸出),並移動到lmer()之後的predict聲明。我怎樣才能做到這一點?

特殊情況可能是第一次迭代失敗時。我們不用擔心這一點。假設循環的第一次迭代總是成功地適合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

我能想到的解決方案,首先,如果你想不覆蓋FM,只是去到下一個聲明:

初始化FM一些初始模型FM0:

fm <- fm0 

然後運行您的循環:

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,因此在下一次迭代中j爲2,且i爲3等等,因此兩個值均遞增1。所以你的代碼是相同的,如果你這樣做

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

而且看起來更好imho。

+0

謝謝!很簡單的解決方案PS:我有'i'和'j'的原因是在我的實際分析中,我正在迭代'Week'。數據從'Week = 1'開始,到'Week = 567'結束。但是,我的數據中只有450個「Week」的唯一值。因此,沿着從1,...的方式,超過100個值的567缺失。我可以在數據中創建一個單獨的變量:'j = 1,...,450',但我認爲'i'和'j'指數同樣簡單。謝謝! – hossibley

+0

好的很高興提供幫助。記得投票並接受答案,如果它幫助:) – latorrefabian