2012-12-03 66 views
9

我試着編寫一個包裝函數來分批做可能性比率測試。我試圖包含update()來更新初始模型。但是,似乎不是在函數內查找對象,而是在全局環境中搜索對象。update()函數裏面只搜索全局環境?

fake <- data.frame(subj= rep(1:5, 4), 
        factor1 = rep(LETTERS[c(1,2,1,2)], each=5), 
        factor2 = rep(letters[1:2], each=10), 
        data=sort(rlnorm(20))) 

foo <- function(){ 
        temp <- fake 
        model1 <- lmer(data~factor1*factor2 + (1 |subj), temp) 
        model1a <- update(model1, ~.-factor1:factor2) 
        model1a} 

,它給下面的錯誤消息:

Error in eval(expr, envir, enclos) : object 'factor1' not found 

反正是有使函數內的update()搜索?謝謝!

編輯:

我犯了一個錯誤。我想通過「臨時」給lmer,而不是「假」。

EDIT2: 建議的一個方便的解決方案是簡單地指定數據對象。雖然更新()現在有這個沒有問題,方差分析()似乎認爲,我想比較模型是基於不同的數據對象

foo <- function(){ 
        temp <- fake 
        model1 <- lmer(data~factor1*factor2 + (1 |subj), data=temp) 
        model1a <- update(model1, ~.-factor1:factor2, data=temp) 
        anova(model1, model1a) 
      } 
foo() 

我得到一個錯誤信息:

Error in anova(model1, model1b) : 
    all models must be fit to the same data object 

我想這個錯誤超越了update()。但我想知道有沒有人知道如何解決這個問題。需要注意的是,如果我寫的功能,而無需使用update()方法,而是拼出來的模型(見下文),上述錯誤就會消失:

foo <- function(){ 
        temp <- fake 
        model1 <- lmer(data~factor1*factor2 + (1 |subj), data=temp) 
        model1a <- lmer(data~factor1 + factor2 + (1 |subj), data=temp) 
        anova(model1, model1a) 
      } 
foo() 

Data: temp 
Models: 
model1a: data ~ factor1 + factor2 + (1 | subj) 
model1: data ~ factor1 * factor2 + (1 | subj) 
     Df  AIC BIC logLik Chisq Chi Df Pr(>Chisq) 
model1a 5 -4.6909 3.7535 7.3454       
model1 6 -8.8005 1.3327 10.4003 6.1097  1 0.01344 * 
--- 
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 

編輯3: 看來這個問題是與方差分析() 。我也@hadley

foo2 <- function(){ 
    my_update <- function(mod, formula = NULL, data = NULL) { 
    call <- getCall(mod) 
    if (is.null(call)) { 
    stop("Model object does not support updating (no call)", call. = FALSE) 
    } 
    term <- terms(mod) 
    if (is.null(term)) { 
    stop("Model object does not support updating (no terms)", call. = FALSE) 
    } 
    if (!is.null(data)) call$data <- data 
    if (!is.null(formula)) call$formula <- update.formula(call$formula, formula) 
    env <- attr(term, ".Environment") 
    eval(call, env, parent.frame())} 

     model1 <- lmer(data~factor1*factor2 + (1 |subj), temp) 
     model1a <- my_update(model1, ~.-factor1:factor2) 
     anova(model1, model1a) 
} 
foo2() 

我得到一個錯誤消息試過的建議,如下圖所示:

Error in as.data.frame.default(data) : 
    cannot coerce class 'structure("mer", package = "lme4")' into a data.frame 
+0

適合我,在R 2.15中沒有錯誤。1,除了需要加載lme4包 – MattBagg

+0

您是否想將'temp'傳遞給'lmer'而不是'fake'? – BenBarnes

+0

對不起,是的,我想把溫度傳給lmer,而不是假的 – Alex

回答

8

我以前也被咬傷也通過這種行爲,所以我寫的update我自己的版本。它評估公式環境中的所有內容,因此它應該相當健壯。

my_update <- function(mod, formula = NULL, data = NULL) { 
    call <- getCall(mod) 
    if (is.null(call)) { 
    stop("Model object does not support updating (no call)", call. = FALSE) 
    } 
    term <- terms(mod) 
    if (is.null(term)) { 
    stop("Model object does not support updating (no terms)", call. = FALSE) 
    } 

    if (!is.null(data)) call$data <- data 
    if (!is.null(formula)) call$formula <- update.formula(call$formula, formula) 
    env <- attr(term, ".Environment") 

    eval(call, env, parent.frame()) 
} 

library(nlme4) 

fake <- data.frame(
    subj = rep(1:5, 4), 
    factor1 = rep(LETTERS[c(1,2,1,2)], each = 5), 
    factor2 = rep(letters[1:2], each = 10), 
    data = sort(rlnorm(20))) 

foo <- function() { 
    temp <- fake 
    model1 <- lmer(data ~ factor1 * factor2 + (1 | subj), fake) 
    model1a <- my_update(model1, ~ . - factor1:factor2) 
    model1a 
} 
foo() 
+0

看來現在的問題是與anova()。我試過你的方法,它與模型更新完美配合。但是,當我嘗試使用anova()時,它給了我一個錯誤信息,如我的原始帖子的編輯3所示。感謝您的幫助! – Alex

+0

@AlexH。,哈德利的答案是要走的路。它以一種與'anova'配合的方式傳遞公式和數據組件。在你上面的'foo2'函數中,你忽略了創建一個'temp'對象,這個對象在被添加時爲我工作。 – BenBarnes

4

雖然我真的很喜歡@哈德利的答案(並將該功能可能自己使用),你也可以指定update功能data說法。 (在這裏,我以爲你想通過temp到您的模型。)

model1a <- update(model1, ~.-factor1:factor2, data = temp) 

編輯

如果你正在尋找與anova比較模型,update將綠豆起來的名稱data爭論和「詭計」anova認爲這兩個模型適合使用兩個不同的數據集。只更新公式並創建一個新模型將避免這種情況:

foo <- function(){ 
        temp <- fake 
        model1 <- lmer(data~factor1*factor2 + (1 |subj), data=temp) 
        newForm <- update.formula(formula(model1), ~.-factor1:factor2) 
        model1a <- lmer(newForm, data=temp) 
        anova(model1, model1a) 
      } 
+0

但是...我認爲這實際上*不*與穩定的'lme4'(我同意它應該)......? –

+0

@BenBolker,有趣的問題。在發佈之前,我成功地在OSX上使用R 2.15.2測試了答案(我很確定)常規的CRAN Mac二進制版本'lme4'。它也可以使用'lme4_0.999999-0'和'Matrix_1.0-9'在WinXP上使用R 2.15.2。 – BenBarnes

+0

對不起,我誤解你在做什麼。 –