On 5/6/2009 12:18 PM, Terrence Ireland wrote:
The following is a simple example with a poor solution that shows my
difficulties with scope. The function /logit.test /has 3 arguments: /model.start,/ an initial model; /model.finish/, an all-inclusive model, /my.data/, a dataset, in this case trivial. There are 2 function calls in l/ogit.test,/ first to /glm/ to get an initial fit (local variable /logit/) using /model.start;/ then a call to /stepAIC/ using the initial fit.

I had thought that l/ogit/ would carry along the dataset, /test.data/ for use in the call to /stepAIC/. Instead it complains that it cannot find /my.data/. It seems to have found the name, not the value in the /call/ attribute. I fixed the problem by creating a global variable /my.data/ within the function,
naming it l/ogit.test.global,/ not a very good solution.

My question is:  How do I handle scope correctly?

The general principle is this:

Variables in formulas are looked up in the data= argument of a modelling function; if that is missing (or the variable was not found), then in the environment where the formula was created.

I haven't traced through the code, but I believe stepAIC also uses the environment of the formula to find the dataset (i.e. it assumes the dataset and formula were created in the same place.

Since you didn't do that, you need some trickery. You want my.data to be found in the environment of the formula. my.data is local to your logit.test function, so changing logit.test to look like this:

logit.test <- function(model.start,model.finish,my.data)
  {
    environment(model.start) <- environment()
    environment(model.finish) <- environment()
    logit <- glm(model.start,binomial(link =
"logit"),my.data,control=glm.control(epsilon=0.0001),x=TRUE,y=TRUE)
    Table <- stepAIC(logit,scope=model.finish,direction="both",trace=1,k=2)
  }

should work. The only potential problem is if your formulas have variables named model.start, model.finish, my.data, logit, or Table: those will be found before global variables of the same name.

I would avoid <<- in logit.test.global, and use the same technique there.

Duncan Murdoch


Thanks,

Terry Ireland

Script of Experiment:

 > library(MASS)

 > test.data
  Approve Score OldScore
1     Yes     1       12
2     Yes     3       10
3     Yes     5        8
4      No     4        9
5      No     6        7
6      No     8        5
 > test.start
Approve ~ 1
 > test.finish
Approve ~ Score + OldScore
 > logit.test
function(model.start,model.finish,my.data)
  {
logit <- glm(model.start,binomial(link = "logit"),my.data,control=glm.control(epsilon=0.0001),x=TRUE,y=TRUE);
    Table <- stepAIC(logit,scope=model.finish,direction="both",trace=1,k=2);
  }
 > logit.test.global
function(model.start,model.finish,my.data)
  {
    my.data <<- my.data
logit <- glm(model.start,binomial(link = "logit"),my.data,control=glm.control(epsilon=0.0001),x=TRUE,y=TRUE);
    Table <- stepAIC(logit,scope=model.finish,direction="both",trace=1,k=2);
  }

 > logit.test(test.start,test.finish,test.data)

In this call, test.start gets assigned to model.start in the function, test.finish to model.finish, and test.data to my.data. Within logit.test, the glm() call looks fine, because you pass my.data to it. But

Start:  AIC=10.32
Approve ~ 1

Error in inherits(x, "data.frame") : object "my.data" not found
 > logit.test.global(test.start,test.finish,test.data)
Start:  AIC=10.32
Approve ~ 1

           Df Deviance     AIC
+ Score     1   4.8089  8.8089
+ OldScore  1   4.8089  8.8089
<none>          8.3178 10.3178

Step:  AIC=8.81
Approve ~ Score

        Df Deviance     AIC
<none>       4.8089  8.8089
- Score  1   8.3178 10.3178
 >

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to