R: функция, переданная как аргумент, не найдена

Я пытаюсь написать простой итеративный перевешенный алгоритм наименьших квадратов в R. Я хочу передать функцию в качестве аргумента для вычисления весов, но, к сожалению, R жалуется, что функция не может быть найдена. Есть идеи, что я делаю неправильно? Заранее спасибо!

вот мой код:

irls <- function(imodel, wfunc, tol) {

    repeat {
        b0 <- imodel$coef
        imodel <- lm(formula(imodel), weights=wfunc(imodel), data=imodel$model)
        b1 <- imodel$coef
        if(abs((b1-b0)/b0)<=tol) break
    }

    imodel
}

и глупый пример, чтобы продемонстрировать проблему

x <- 1:100
y <- x + rnorm(100)
mlm <- lm(y~x-1)
irls(mlm, function(x){rep(1,length(x$fit))},0.001) # error: wfunc not found

3 ответов


проблема заключается в том, как lm ищет данные. Если вы измените функцию на это, она, кажется, работает

irls <- function(imodel, wfunc, tol) {

    repeat {
        b0 <- imodel$coef
        dat <- imodel$model
        dat$wts <- wfunc(imodel)
        imodel <- lm(formula(imodel), weights=wts, data=dat)
        b1 <- imodel$coef
        if(abs((b1-b0)/b0)<=tol) break
    }

    imodel
}

на formula содержит среду начального lm вызов (.GlobalEnv в этом случае), в которой wfunc был недоступен. В качестве обходного пути вы можете заменить его текущей средой.

irls <- function(imodel, wfunc, tol) {
  f <- formula(imodel)
  environment(f) <- environment()
  repeat {
    b0 <- imodel$coef
    imodel <- lm(f, weights=wfunc(imodel), data=imodel$model)
    b1 <- imodel$coef
    if(abs((b1-b0)/b0)<=tol) break
  }
  imodel
}
irls(mlm, function(x){rep(1,length(x$fit))},0.001)

эта проблема возникает потому, что model.frame.default внутри lm, который оценивает все в среде формулы:

model.frame.default
#function (formula, data = NULL, subset = NULL, na.action = na.fail, 
#    drop.unused.levels = FALSE, xlev = NULL, ...) 
#{
#...
#    env <- environment(formula)
#...
#    extras <- eval(extras, data, env)  <-- this is where you run into a problem
#...

так как другие предложили, оцените функцию вне lm.