2017-05-29 1 views
1

Ich frage mich, ob es eine Base R-Funktion gibt, um die Argumentwerte zu extrahieren, die in einem bestimmten Funktionsaufruf verwendet werden?Wie kann man herausfinden, welche Argumentwerte in einem R-Funktionsaufruf verwendet wurden?

Zum Beispiel für jedes der Objekte x, y und z unten gibt es eine generische Art und Weise die Argumente Namen zu extrahieren (zB n, sd, rate, scale) im Einsatz und die Werte (zB 1e4 für n) zugewiesen von dem Benutzer oder dem System zu jedem dieser Argumente?

HINWEIS: in bestimmten "R" -Funktionen ist eine solche Extraktion einfach durchzuführen. Zum Beispiel kann in density() das Argument values unter Verwendung von density()$call einfach extrahiert werden.

x = rnorm(n = 1e4, mean = 2, sd = 4) 
y = rlogis(1e4, 20) 
z = rexp(1e4, 5) 
+1

AFAIK, würden Sie den Anruf sparen müssen und analysieren sie, welche Art von Schmerz ist. – alistaire

+1

wie @alistaire sagte, Sie können auf den Aufruf innerhalb einer Funktion mit 'Sys.call()' zugreifen ... Aber was ist Ihr Ziel? – Val

Antwort

2

Das ist wirklich keine einfache Sache zu tun. Wenn Sie die Funktion Gebäude sind, können Sie den Anruf mit match.call, erfassen, die ohne allzu viel Mühe analysiert werden kann:

f <- function(x, y = 1, ...){ 
    cl <- match.call() 
    as.list(cl[-1]) 
} 

str(f(1)) 
#> List of 1 
#> $ x: num 1 

str(f(1, 'foo')) 
#> List of 2 
#> $ x: num 1 
#> $ y: chr "foo" 

str(f(1, 'foo', list(3), fun = sum)) 
#> List of 4 
#> $ x : num 1 
#> $ y : chr "foo" 
#> $ : language list(3) 
#> $ fun: symbol sum 

Hinweis match.call erfasst nur den Anruf, und nicht fügen in Standardparametern (Im ersten Beispiel gibt es keine y. Diese können mit formals(f) zugegriffen werden, da f nicht primitiv ist, so vollständig Argumente könnten über

user_args <- f(1) 
fun_args <- formals(f) 
fun_args[names(user_args)] <- user_args 

str(fun_args) 
#> List of 3 
#> $ x : num 1 
#> $ y : num 1 
#> $ ...: symbol 

Dieser Ansatz funktioniert nicht gut für erledigte Punkte erzeugt werden, aber wenn sie dann match.call selbst abgeschlossen sollte ausreichen . Um die an eine existierende Funktion übergebenen Parameter zu extrahieren, könnten Sie einen Wrapper mit match.call schreiben, aber es ist kaum praktikabel, jede Funktion zu rekonstruieren, und der Aufruf, den Sie erfassen, wird sowieso lustig aussehen, wenn Sie bestehende Funktionen nicht überschreiben. Solange die Funktion nicht primitiv, Sie quote verwenden könnte den formals Ansatz zu ermöglichen, aber:

cl <- quote(rnorm(5, 2)) 
user_args <- as.list(cl[-1]) # subset call to only args 
fun_args <- formals(as.character(cl[1])) # subset call to only function 
names(user_args) <- names(fun_args)[seq(length(user_args))] 
fun_args[names(user_args)] <- user_args 

str(fun_args) 
#> List of 3 
#> $ n : num 5 
#> $ mean: num 2 
#> $ sd : num 1 

Ein anderer Ansatz ist rlang zu verwenden, deren Funktionen handhaben Primitiven gut (fn_fmls(sum)) können Teile extrahieren der Anruf einfach und zuverlässig (lang_fn, lang_args), unbenannte Parameter genau benennen (lang_standardize) und mehr. Zusammen mit purrr Der neue list_modify (dev-Version), es wird alles ziemlich schmerzlos:

library(rlang) 

fun_call <- quo(rnorm(5)) 
fun_call 
#> <quosure: frame> 
#> ~rnorm(5) 

default_args <- fn_fmls(lang_fn(fun_call)) 
str(default_args) 
#> Dotted pair list of 3 
#> $ n : symbol 
#> $ mean: num 0 
#> $ sd : num 1 

user_args <- lang_args(lang_standardise(fun_call)) 
str(user_args) 
#> List of 1 
#> $ n: num 5 

calling_args <- purrr::list_modify(default_args, user_args) 
str(calling_args) 
#> Dotted pair list of 3 
#> $ n : num 5 
#> $ mean: num 0 
#> $ sd : num 1 
Verwandte Themen