2016-04-01 10 views
3

Ich habe Liste von Funktionen, die auch eine benutzerdefinierte Funktion enthält:wie Variablennamen aus der Liste zu bekommen

> fun <- function(x) {x} 
> funs <- c(median, mean, fun) 

Ist es möglich, Funktionsnamen als Strings aus dieser Liste zu bekommen? Meine einzige Lösung war bisher Vektor zu schaffen, die Funktionsnamen als Strings enthält:

> fun.names <- c("median", "mean", "fun") 

Wenn ich Variablennamen bekommen verwende ich diesen Trick tun (wenn dies nicht mich korrigieren, korrigieren Sie bitte), aber wie Sie können es funktioniert nur für eine Variable nicht für die Liste:

> as.character(substitute(mean)) 
[1] "mean" 

> as.character(substitute(funs)) 
[1] "funs" 

Gibt es etwas, das auch für die Liste funktioniert? Gibt es einen Unterschied, wenn die Liste Funktionen oder Datentypen enthält?

EDIT: Ich muss diese Liste von Funktionen (plus andere Daten) an eine andere Funktion übergeben. Dann werden diese Funktionen aus der Liste auf das Dataset angewendet. Funktionsnamen werden benötigt, denn wenn in der Liste mehrere Funktionen übergeben werden, möchte ich feststellen können, welche Funktion angewendet wurde. Bisher habe ich das schon mit:

window.size <- c(1,2,3) 
combinations <- expand.grid(window.size, c(median, mean)) 
combinations <- cbind(combinations, rep(c("median","mean"), each = length(window.size))) 
+3

Etwas mehr Hintergrund, wie die Liste erstellt wird, würde helfen, weil die übliche Lösung wäre, die Liste mit Namen an erster Stelle zu erstellen. Es würde also helfen zu sehen, ob/warum Sie das in diesem Fall nicht tun können. – joran

+0

Wie @joran sagt, wirst du "Namen" haben, wenn du 'Spaß <-c (Median = Median, Mittelwert = Mittelwert, Spaß = Spaß)' – HubertL

+1

schreibst Für eine wirklich exotische Variante, da du unsere Fragen nicht angesprochen hast, [this] (http://stackoverflow.com/q/21011672/324364) Frage zeigt, wie eine Funktion geschrieben wird, die eine "automatisch" benannte Liste erstellt. – joran

Antwort

1

Hier ist ein Hacky Ansatz:

funs <- list(median, mean) 

fun_names = sapply(funs, function(x) { 
    s = as.character(deparse(eval(x)))[[2]] 
    gsub('UseMethod\\(|[[:punct:]]', '', s) 
}) 

names(funs) <- fun_names 

funs 

$median 
function (x, na.rm = FALSE) 
UseMethod("median") 
<bytecode: 0x103252878> 
<environment: namespace:stats> 

$mean 
function (x, ...) 
UseMethod("mean") 
<bytecode: 0x103ea11b8> 
<environment: namespace:base> 

combinations <- expand.grid(window.size, fun_names, c(median, mean)) 
2

Im Allgemeinen ist dies nicht möglich. Betrachten Sie diese Definition von funs:

funs <- c(median,mean,function(x) x); 

In diesem Fall gibt es keinen Namen mit der benutzerdefinierten Funktion zugeordnet ist überhaupt nicht. Es gibt keine Regel in R, die besagt, dass alle Funktionen zu einem bestimmten Zeitpunkt an einen Namen gebunden sein müssen.

Wenn Sie einige Annahmen über ob starten wollen machen und wo alle solche lambdas definiert sind, dann Möglichkeiten eröffnen.

Eine Idee besteht darin, die Schließumgebung jeder Funktion nach einem Eintrag zu suchen, der (identisch) mit der Funktion selbst übereinstimmt und diesen Namen dann verwendet. Dies wird eine Leistungseinbuße aufgrund der Vergleichsarbeit entstehen, aber erträglich sein kann, wenn Sie es nicht laufen wiederholt haben:

getFunNameFromClosure <- function(fun) names(which(do.call(c,eapply(environment(fun),identical,fun)))[1L]); 

Demo:

fun <- function(x) x; 
funs <- c(median,mean,fun); 
sapply(funs,getFunNameFromClosure); 
## [1] "median" "mean" "fun" 

Caveats:

1: Wie bereits erläutert, funktioniert dies nicht für Funktionen, die nie an einen Namen gebunden waren. Außerdem funktioniert es nicht bei Funktionen, deren Closure-Umgebung keine Bindung an die Funktion enthält. Dies kann passieren, wenn die Funktion an einen Namen in einer anderen Umgebung gebunden wurde als an deren Schließung (über einen Rückgabewert, Superassignment oder assign()) oder wenn ihre Abschlussumgebung explizit geändert wurde.

2: Es ist möglich, eine Funktion an mehrere Namen zu binden. Daher ist der Name, den Sie als Ergebnis der eapply()-Suche erhalten, möglicherweise nicht der, den Sie erwarten.Hier ist eine gute Demonstration davon:

getFunNameFromClosure(ls); ## gets wrong name 
## [1] "objects" 
identical(ls,objects); ## this is why 
## [1] TRUE 
+1

Gute Analyse. Es ist informativ, 'dput (Spaß)' zu betrachten. Es zeigt, dass die "Namen" dieser Objekte bereits gesucht wurden und nur ihr Wert in dem zurückgegebenen Objekt von der Operation 'funs <- c (mean.median, fun) 'übrig bleibt. Es ist ein bisschen wie das, was in 'lapply' passiert, wo Leute erwarten, dass sie Namen finden können, aber nur Werte innerhalb von Funktionen erhalten. Die Namen werden später neu vergeben. –

Verwandte Themen