2016-07-31 5 views
1

Я создаю обертку вокруг lm, чтобы выполнить некоторые дополнительные вычисления. Я хотел бы, чтобы обертка прошла ... до lm, но я столкнулся с проблемой lm аргументом weights.Проблема с Эллипсисом: Прохождение ... до lm

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

Если я называю обертку с аргументом веса,

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

R не знает, где искать весов:

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

lm страница помощи говорит

Все weights, subset и 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 напрямую, работает просто отлично:

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

ответ

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

Код выше не самый красивый, но он работает как subset и weights. Кроме того, вы можете просто обрабатывать weights и subset в качестве исключений.