Ellipsis Trouble: Passing … to lm

无人久伴 提交于 2019-12-08 07:56:44

问题


I am building a wrapper around lm to do some additional calculations. I'd like the wrapper to pass ... to lm, but I am getting into trouble with lm's weights argument.

LmWrapper <- function(df, fmla, ...) {
  est <- lm(fmla, df, ...)
  list(model = est)
}

If I call the wrapper with a weights argument,

data(airquality)
LmWrapper(airquality, Ozone ~ Wind, weights = Temp)

R does not know where to look for the weights:

Error in eval(expr, envir, enclos) : 
  ..1 used in an incorrect context, no ... to look in

The lm help page says

All of weights, subset and offset are evaluated in the same way as variables in formula, that is first in data and then in the environment of formula.

but the wrapper seems to change things.

How do I fix this?


The traceback() for the above error looks like this:

8: eval(expr, envir, enclos)
7: eval(extras, data, env)
6: model.frame.default(formula = fmla, data = df, weights = ..1, 
       drop.unused.levels = TRUE)
5: stats::model.frame(formula = fmla, data = df, weights = ..1, 
       drop.unused.levels = TRUE)
4: eval(expr, envir, enclos)
3: eval(mf, parent.frame())
2: lm(fmla, df, ...) at #2
1: LmWrapper(diamonds, price ~ carat, weights = depth)

Calling lm directly, works just fine:

lm(Ozone ~ Wind, airquality, weights = Temp)

回答1:


So the problem is that lm normally looks up those names in argument data but somehow scoping goes wrong. You can fix that by looking up column references and passing them on manually.

LmWrapper <- function(df, fmla, ...) {
  # get names of stuff in ...
  argNames = sapply(substitute(list(...))[-1L], deparse)
  # look for identical names in df
  m = match(names(df), argNames, 0L)
  # store other arguments from ... in a list
  args = list(eval(parse(text = argNames[-m])))
  # name the list
  names(args) = names(argNames[-m])
  # store complete values in args, instead of just references to columns
  # the unlist code is rather ugly, the goal is to create a list where every
  # element is a column of interest
  args[names(argNames)[m]] = unlist(apply(df[, as.logical(m), drop = FALSE], 
                                       2, list), recursive = FALSE)
  # also put other stuff in there
  args$formula = fmla
  args$data = df
  # do lm
  est = do.call(lm, args)
  list(model = est)
}

data(airquality)

airquality$subset = airquality$Solar.R > 200
LmWrapper(airquality, Ozone ~ Wind, weights = Temp, subset = subset, 
          method = 'qr')

The code above is not the most beautiful, but it works for both subset and weights. Alternatively, you could just handle weights and subset as exceptions.



来源:https://stackoverflow.com/questions/38683076/ellipsis-trouble-passing-to-lm

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!