2009-04-21 9 views
7

J'ai essayé d'en apprendre plus sur R (et d'écrire des extensions C) et j'ai pensé que cela pourrait aider à lire la source de certains paquets bien connus. J'ai décidé de commencer par rpart qui est défini comme:Comment utiliser un paramètre de fonction sans le mentionner dans le corps de la fonction?

rpart <- function(formula, data, weights, subset, 
     na.action=na.rpart, method, model=FALSE, x=FALSE, y=TRUE, 
     parms, control, cost, ...) 

Je l'ai fait une recherche rapide à travers la source et je ne vois pas la formule mentionnée nulle part dans le encore corps de la fonction, je sais que rpart est en quelque sorte en utilisant ce paramètre. Comment est-ce que rpart utilise la formule sans que son nom soit dans le corps de la fonction?

Répondre

9

Il est assez délicat:

m <- match.call(expand.dots = FALSE) 
# ... 
m[[1L]] <- as.name("model.frame") 
m <- eval(m, parent.frame()) 

La fonction utilise match.call pour savoir comment on l'appelle, modifie l'appel à remplacer la fonction appelée par model.frame, et il appelle via eval avec les paramètres qu'il a reçus (bien que la partie que j'ai remplacée par # ... supprime plusieurs des paramètres), et model.frame utilise le paramètre formula. Voir la documentation de match.call, eval et model.frame, et expérimenter un peu, par ex. essayer de comprendre ce qui se passe ici:

f <- function(formula, data) { 
    m <- match.call() 
    m[[1L]] <- as.name('model.frame') 
    eval(m, parent.frame()) 
} 
f(x ~ y) 
Error in eval(expr, envir, enclos) : object 'x' not found 
x <- c(1,2,3) 
f(x ~ y) 
Error in eval(expr, envir, enclos) : object 'y' not found 
y <- c(3,4,5) 
f(x ~ y) 
    x y 
1 1 3 
2 2 4 
3 3 5 
d <- as.data.frame(matrix(c(1,2,3,4),nrow=2)) 
names(d) <- c('foo', 'bar') 
f(foo ~ bar, d) 
    foo bar 
1 1 3 
2 2 4