2016-07-31 51 views
1

我正在構建一個圍繞lm的包裝來做一些額外的計算。我想包裝通過...lm,但我陷入了lmweights論點的麻煩。省略號故障:傳遞...到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,subsetoffset的評估方式與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') 

上面的代碼是不是最漂亮的,但它同時適用於subsetweights。或者,您可以將weightssubset作爲例外。