Reputation: 13914
I would like to able to call lm
within a function and specify the weights
variable as an argument passed to the outside function that is then passed to lm
. Below is a reproducible example where the call works if it is made to lm
outside of a function, but produces the error message Error in eval(expr, envir, enclos) : object 'weightvar' not found
when called from within a wrapper function.
olswrapper <- function(form, weightvar, df){
ols <- lm(formula(form), weights = weightvar, data = df)
}
df <- mtcars
ols <- lm(mpg ~ cyl + qsec, weights = gear, data = df)
summary(ols)
ols2 <- olswrapper(mpg ~ cyl + qsec, weightvar = gear, df = df)
#Produces error: "Error in eval(expr, envir, enclos) : object 'weightvar' not found"
Upvotes: 7
Views: 4245
Reputation: 86
eval(substitute(...))
inside a body of a function allows us to employ non-standard evaluation
df <- mtcars
olswrapper <- function(form, weightvar, df)
eval(substitute(ols <- lm(formula(form), weights = weightvar, data = df)))
summary(ols)
olswrapper(mpg ~ cyl + qsec, weightvar = gear, df = df)
More here: http://adv-r.had.co.nz/Computing-on-the-language.html
Upvotes: 2
Reputation: 1812
I know I'm late on this, but I believe the previous explanation is incomplete. Declaring weightvar <- df$gear
and then passing it in to the function only works because you use weightvar
as the name for your weight argument. This is just using weightvar
as a global variable. That's why df$gear
doesn't work directly. It also doesn't work if you use any name except weightvar
.
The reason why it doesn't work is that lm looks for data in two places: the dataframe argument (if specified), and the environment of your formula. In this case, your formula's environment is R_GlobalEnv
. (You can test this by running print(str(form))
from inside olswrapper
). Thus, lm
will only look in the global environment and in df
, not the function environment.
edit: In the lm
documentation the description of the data argument says:
"an optional data frame, list or environment (or object coercible by as.data.frame to a data frame) containing the variables in the model. If not found in data, the variables are taken from environment(formula), typically the environment from which lm is called."
A quick workaround is to say environment(form) <- environment()
to change your formula's environment. This won't cause any problems because the data in the formula is in the data frame you specify.
Upvotes: 2
Reputation: 8333
Building on the comments, gear
isn't defined globally. It works inside the stand-alone lm
call as you specify the data you are using, so lm
knows to take gear
from df
.
Howver, gear
itself doesn't exist outside that stand-alone lm
function. This is shown by the output of gear
> gear
Error: object 'gear' not found
You can pass the gear
into the function using df$gear
weightvar <- df$gear
ols <- olswrapper(mpg ~ cyl + qsec, weightvar , df = df)
Upvotes: 3