This is a very trimmed down version of what I want to do, I can't paste my exact problem cause the code is too long and complex but I think this gets at the root of issue. Thanks to Josh's answer to this question How do you code an R function so that it 'knows' to look in 'data' for the variables in other arguments? I'm part way there.
example <- function(model, xvar3=NULL, xvar4=NULL, data){
print(class(model))
#xvar3 <- eval(substitute(xvar3), envir=data, enclos=parent.frame())
#xvar4 <- eval(substitute(xvar4), envir=data, enclos=parent.frame())
print(class(xvar3))
xvar5 <- xvar4^2
mod <- glm( model + xvar3 + xvar5, data=data)
return(mod)
}
example(mpg ~ cyl, hp, wt, data=mtcars)
This fails. If you remove the comments (based on help from previous question) it solves the problem of 'finding' hp and wt. 'model' is of class formula and I would like that to become 'mpg ~ cyl + xvar3 + xvar5' so that the glm will run. But I can't seem to be able to add them to the formula.
I've been toying around with 'call' classes and further with 'eval', and 'as.formula' with variations of 'paste' and 'noquote' etc but can't see to get it to stick.
Answer
Here's one way. The trick I used is to create a new formula based on the given one + the two extra variables. I then did a trick with the environment of the formula so that both xvar3
/xvar5
AND any variables local to the caller can be used.
glm
will always look in the formula's environment AND in the data for variables (and nowhere else!). That's why the formula environment must the manipulated a bit in this case: it contains xvar3
and xvar5
, and the parent environment is set to the original formula's environment so that it is also searched for variables (foo
in the last example)...
example <- function(model, xvar3=NULL, xvar4=NULL, data){
e <- new.env(parent=environment(model))
e$xvar3 <- eval(substitute(xvar3), envir=data, enclos=parent.frame())
e$xvar4 <- eval(substitute(xvar4), envir=data, enclos=parent.frame())
e$xvar5 <- e$xvar4^2
model <- update(model, . ~ . + xvar3 + xvar5)
environment(model) <- e
mod <- glm(model, data=data)
return(mod)
}
example(mpg ~ cyl, hp, wt, data=mtcars)
# Using a local variable should work too:
doit <- function(d) {
foo <- d$cyl+1
example(mpg ~ foo, hp, wt, data=d)
}
doit(mtcars)
No comments:
Post a Comment