简体   繁体   中英

R - Pass optional arguments to nested functions

I would like to write a function and calls different sub-functions with parameters specified by string, such as:

genericModel <- function(model, dat, y, x, ...) {
    fit <- get(model)(get(y) ~ get(x), data = dat, ...)
    return(fit)
}

I am able to get it to work with simple cases:

> d <- data.frame(x.var = rnorm(10), y.var = rnorm(10), w = rep(1, 10))
> genericModel('lm', d, 'y.var', 'x.var')

Call:
get(model)(formula = get(y) ~ get(x), data = dat)

Coefficients:
(Intercept)       get(x)  
   -0.04242     -0.31619 

However, I have not been successful in terms of passing other optional arguments by string:

> genericModel('lm', d, 'y.var', 'x.var', weights = 'w')
Error in model.frame.default(formula = get(y) ~ get(x), data = dat, weights = "w",  : 
  variable lengths differ (found for '(weights)')

I know I can do genericModel('lm', d, 'y.var', 'x.var', weights = d$w) , but that defeats the purpose of creating a flexible function where I can specify the model and column names by string.

Also I can foresee complications where the optional parameters include both column names of the data.frame(ex: weights = w ) and generic options for the sub-function(ex: na.action=na.pass ).

EDIT: Just to clarify, what I am hoping to achieve is:

genericModel('lm', d, 'y.var', 'x.var', weights = 'w')
genericModel('glm', d, 'y.var', 'x.var', family = 'binomial')

To run linear regression and logistic regression, respectively. I need some way to pass the optional arguments when calling genericModel.

Does anyone know how to deal with this? Thanks.

One suggestion: rather than fiddling with strings to specify analysis variables, what you should do is pass the formula. This is also much more flexible, since you'll be able to pass complicated model formulas directly to the underlying functions without any parsing.

If you do this, then obtaining what you want is simple with some language hacking. Get the call to the function, then manipulate it to call the model-fitting function instead.

genericModel <- function(mod, formula, data, ...)
{
    cl <- match.call(expand=TRUE)
    cl[[1]] <- cl$mod
    cl$mod <- NULL
    eval(cl, parent.frame())
}

genericModel(lm, mpg ~ hp, data=mtcars, weights=gear)
genericModel(glm, Volume ~ Girth + Height, data=trees, family=Gamma(link=log))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM