Does Update () inside a function execute only the global environment?

I tried to write a wrapper function to run package likelihood tests. I tried to enable update () to update the original model. However, it seems that instead of searching for objects within a function, it searches for objects in the global environment.

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} 

And the error message below appears:

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

Is there a way to do update () a search inside a function? Thank!

EDIT:

I made a mistake. I wanted to pass "temp" to lmer, not fake.

EDIT2: One convenient solution is to simply specify a data object. Although update () now has no problems with this, anova () seems to believe that the models I'm trying to compare are based on different data objects.

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

The error message appears:

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

I assume this error is beyond the scope of update (). But I wonder if anyone knows how to solve this. Please note: if I write a function without using update () and instead produce samples (see below), the error above will go away:

  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 

EDIT 3: It seems the problem is with anova (). I also tried @hadley's suggestion

 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() 

I got an error message as shown below:

  Error in as.data.frame.default(data) : cannot coerce class 'structure("mer", package = "lme4")' into a data.frame 
+9
function r environment
Dec 03 '12 at 19:22
source share
2 answers

I was also bitten by this behavior, so I wrote my own version of update . He evaluates everything in the midst of the formula, so he must be strong enough.

 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() 
+8
Dec 03 '12 at 20:14
source share

Although I really like @Hadley's answer (and most likely he will use this function on his own), you can also specify the data argument in the update function. (Here I assumed that you wanted to pass temp your models.)

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



EDIT

If you want to compare models with anova , update display the name of the data argument and the anova trick, assuming the two models were usable using two different data sets. Updating only formulas and creating a new model will avoid this:

 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) } 
+4
Dec 03
source share



All Articles