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