省略号麻烦:传递给lm

时间:2016-07-31 10:34:19

标签: r lm ellipsis

我正在围绕lm构建一个包装器来进行一些额外的计算。我希望包装器将...传递给lm,但我遇到了lm的{​​{1}}参数问题。

weights

如果我用权重参数调用包装器,

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

R不知道在哪里寻找重量:

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

Error in eval(expr, envir, enclos) : ..1 used in an incorrect context, no ... to look in 帮助页面显示

  

所有lmweightssubset的评估方式与offset中的变量相同,即formula中的变量,然后是data的环境。

但包装器似乎改变了一些东西。

我该如何解决这个问题?

上述错误的formula如下所示:

traceback()

直接致电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) ,效果很好:

lm

2 个答案:

答案 0 :(得分:2)

所以问题是lm通常在参数数据中查找这些名称,但某种方式确定了问题。您可以通过查找列引用并手动传递它来解决此问题。

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')

上面的代码不是最漂亮的,但它适用于subsetweights。或者,您可以将weightssubset作为例外处理。

答案 1 :(得分:0)

感谢范德曼(Vandenman)的回答。我刚刚实现了两个共享的更改,以防其他人遇到此线程:

1)如果...中除了数据列之外没有参数,则上述代码在列表中创建一个NA元素,并引发警告-我在下面添加了一个条件来解决此问题。

2)上面代码返回的模型对象调用非常长,因为它包含每个权重等。如果您不关心使用update()的能力,那么替换它可能会更有见地通过实际的函数调用来记录发生的情况,如下所述。

run_lm <- function(df, formula, ...) {
    # 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, if any
    dot_args <- eval(parse(text = argNames[-m]))
    if (is.null(dot_args)) {args <- list()
    } else {
      args <- list(dot_args)
      # 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 = formula
    args$data = df
    # do lm
   mod <- do.call(lm, args)
   mod$call <- sys.call()
   mod
   }