2013-08-22 3 views
8

Ich versuche, einen einfachen iterativen reweighted Least Squares-Algorithmus in R zu schreiben. Ich möchte eine Funktion als Argument für die Berechnung der Gewichte übergeben, aber leider klagt R, dass die Funktion nicht gefunden werden. Irgendwelche Ideen, was ich falsch mache? Danke im Voraus!R: Funktion übergeben als Argument wird nicht gefunden

Hier ist mein Code:

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 
} 

und ein dummes Beispiel das Problem

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 
+1

Seltsam. Es scheint, das Problem ist in "lm". Wenn es versucht, die Funktion in der folgenden Zeile zu finden: 'mf <- eval (mf, parent.frame())' – nograpes

+0

Es kann helfen: http://stackoverflow.com/questions/7027288/error-could-not- find-function-in-r – Fernando

+1

Ich denke, du bist besser dran, deine Funktion zuerst zu definieren. 'wfunc <-funktion (x) {rep (1, length (x $ fit))}' gefolgt von 'irls (mlm, wfunc, 0.001)' –

Antwort

8

Das Problem kommt mit bis zu zeigen, wie lm für die Daten sieht. Wenn Sie die Funktion auf das ändern scheint es

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 
} 
+1

Dang du Ninja mich! –

+0

Vielen Dank :) – linuxfever

5

Die formula enthält die Umgebung des anfänglichen lm Aufruf (.GlobalEnv, in diesem Fall) zu arbeiten, in denen wfunc nicht verfügbar war. Um dieses Problem zu umgehen, können Sie es durch die aktuelle Umgebung ersetzen.

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) 
+0

Sie müssen es nur einmal tun - nicht jedes Mal. – hadley

+0

@hadley: guter Punkt. Ich habe die Formel außerhalb der Schleife verschoben. –

-1

Dieses Problem entsteht, weil model.frame.default innerhalb lm genannt wird, was alles in der Umgebung der Formel auswertet:

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 
#... 

So wie die andere vorgeschlagen haben, außerhalb von lm die Funktion auszuwerten.

+0

und der Grund für den Downvote ist ... – eddi