函数内的update()只搜索全局环境? [英] update() inside a function only searches the global environment?

查看:105
本文介绍了函数内的update()只搜索全局环境?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图编写一个包装函数来批量进行似然比测试。我试图包含update()来更新初始模型。但是,似乎不是在函数内查找对象,而是在全局环境中搜索对象。

 假<  -  data.frame(subj = rep(1:5,4),
factor1 = rep (字母[c(1,2,1,2)],每个= 5),
factor2 = rep(字母[1:2],每个= 10),
data = sort(rlnorm( 20)))

foo< - function(){
temp< - false
model1< - lmer(data_factor1 * factor2 +(1 | subj) ,temp)
model1a< - update(model1,〜。factor1:factor2)
model1a}

它在下面给出了一个错误信息:

pre $ eval(expr,envir,enclos)中的错误: object'factor1'not found

有没有办法在函数中进行update()搜索?谢谢!



编辑:



我犯了一个错误。我想将temp传递给lmer,而不是假。

编辑2:
建议的一个简便解决方案是简单地指定数据对象。尽管update()现在没有问题,但anova()似乎认为我试图比较的模型是基于不同的数据对象的。 code $ f $< - function(){
temp< - 假
model1< -lmer(data_factor1 * factor2 +(1 | subj),data = temp)
model1a< - update(model1,〜。factor1:factor2,data = temp)
anova(model1,model1a)
}
foo()

我收到一条错误消息:

 在anova(model1,model1b)中出错:
所有模型必须适合相同的数据对象

我想这个错误超出了update()。但我想知道有没有人知道如何解决这个问题。请注意,如果我在不使用update()函数的情况下编写函数,而是拼写出模型(参见下文),则上述错误消失:

  foo < -  function(){
temp < - 假
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。代码:0'***'0.001'**'0.01'*'0.05'。'0.1''1

编辑3:
看来这个问题是与anova()。我也尝试了@hadley的建议

$ p $ foo2 < - function(){
my_update< - function( mod,公式= NULL,data = NULL){
调用< - getCall(mod)
if(is.null(call)){
stop(Model object does not support updating (无法呼叫),call。= FALSE)
}
term< - terms(mod)
if(is.null(term)){
stop(Model (!is.null(data))调用$ data< - data
if(!is .nu​​ll(公式))调用$ formula< - update.formula(调用$ formula,formula)
env < - attr(term,.Environment)
eval(call,env,parent (model_1,〜factor1),...,b1,...,b1,...,b1,..., :factor2)
anova(model1,model1a)
}
foo2()

我收到了一条错误消息,如下所示:

  as.data.frame.default中的错误(da ta):
不能强制将类的结构(mer,package =lme4)'转换为data.frame

$ b $我之前也被这种行为叮咬过,所以我写了自己的版本 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)
}
如果(is.null(term)){
stop(模型对象不支持更新(无条件),call。= FALSE)
,如果(!is.null(数据))调用$ data< - data
,则调用$ formula< - update.formula();}

if调用$ 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)],每个= 5),
factor2 = rep(字母[1:2],每个= 10),
data = sort(rlnorm(20) ))

foo < - function(){
temp < - false
model1 <-lmer(data_factor1 * factor2 +(1 | subj),false )
model1a< - my_upda te(model1,〜。 - factor1:factor2)
model1a
}
foo()


I tried to write a wrapper function to do likelihood ratio tests in batches. I tried to include update() to update the initial model. However, it seems that instead of looking for objects inside the 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 it gives an error message below:

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

Is there anyway to make update() search within the function? Thank you!

EDIT:

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

EDIT2: One convenient solution suggested is to simply specify the data object. Although update() now has no problem with this, anova() seems to think that the models I am 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()

I get an error message:

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

I suppose this error goes beyond update(). But I wonder if anyone knows how this can be resolved. Note that if I write the function without using update() and instead spell out the models (see below), the error above goes 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 that the issue is with anova(). I also tried the suggestion by @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()

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

解决方案

I've been bitten by this behaviour before too, so I wrote my own version of update. It evaluates everything in the environment of the formula, so it should be fairly robust.

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

这篇关于函数内的update()只搜索全局环境?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆