2013-10-02 15 views
17

Ich habe festgestellt, dass einige Pakete erlauben, Symbolnamen zu übergeben, die möglicherweise nicht einmal in dem Kontext gültig sind, in dem die Funktion aufgerufen wird. Ich frage mich, wie das funktioniert und wie ich es in meinem eigenen Code verwenden kann? HierÜbergabe eines Variablennamens an eine Funktion in R

ist ein Beispiel mit ggplot2:

a <- data.frame(x=1:10,y=1:10) 
library(ggplot2) 
qplot(data=a,x=x,y=y) 

x und y nicht in meinem Namensraum existieren, aber ggplot versteht, dass sie einen Teil des Datenrahmens sind und verschiebt deren Auswertung zu einem Kontext, in dem sie sind gültig. Ich habe versucht, das gleiche tun:

b <- function(data,name) { within(data,print(name)) } 
b(a,x) 

Doch dies scheitert kläglich:

Error in print(name) : object 'x' not found 

Was mache ich falsch? Wie funktioniert das?

Hinweis: Das ist nicht ein Duplikat Pass variable name to a function in r

Antwort

13

Ich weiß, dass dies ein älteres Faden, aber es ist, den ich in der Vergangenheit bezeichnet habe. Ich habe kürzlich entdeckt, was ich für einen besseren Ansatz zum Übergeben von Variablennamen halte. Also dachte ich, ich würde es aufnehmen. Ich hoffe, das hilft jemandem.

a <- data.frame(x = 1:10, y = 1:10) 

b <- function(df, name){ 
    eval(substitute(name), df) 
} 

b(a, x) 
    [1] 1 2 3 4 5 6 7 8 9 10 

-Update Der Ansatz nutzt nicht Standardauswertung. Ich begann zu erklären, erkannte aber schnell, dass Hadley Wickham es viel besser macht als ich. Lesen Sie diese http://adv-r.had.co.nz/Computing-on-the-language.html

+1

Könnten Sie ein bisschen mehr (ein paar Kommentare hinzufügen)? Dieser Ansatz klingt interessant. Beachten Sie, dass es beim Stack-Overflow keine "alten Threads" gibt, Informationen bleiben für Leute wie Sie und mich erhalten, die ihre Fragen googeln. –

+1

@static_rtti Ich habe die Antwort aktualisiert. HTH –

+1

Dies ist ein Juwel einer Antwort, danke. Wenn es hilft, dann gibt 'var <- eval (substitute (var), data)' Ihnen das Objekt, dann gibt 'var.name <- substitute (var)' Ihnen den Variablennamen, der in der Funktion verwendet wird. – drstevok

9

du match.call zum Beispiel mit tun können:

b <- function(data,name) { 

    ## match.call return a call containing the specified arguments 
    ## and the function name also 
    ## I convert it to a list , from which I remove the first element(-1) 
    ## which is the function name 

    pars <- as.list(match.call()[-1]) 
    data[,as.character(pars$name)] 

} 

b(mtcars,cyl) 
[1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4 

Erklärung:

match.call liefert ein Aufruf, bei dem alle angegebenen Argumente sind spezifiziert durch ihre vollen Namen.

Also hier die Ausgabe von match.call 2 Symbole:

b <- function(data,name) { 
    str(as.list(match.call()[-1])) ## I am using str to get the type and name 
} 

b(mtcars,cyl) 
List of 2 
$ data: symbol mtcars 
$ name: symbol cyl 

So Dann benutze ich erste Symbol mtcars ansd wandeln die zweite in einen String:

mtcars[,"cyl"] 

oder äquivalent zu:

eval(pars$data)[,as.character(pars$name)] 
+0

Könnten Sie ein bisschen erklären, wie es funktioniert? –

+1

@static_rtti Ich füge eine Erklärung hinzu. Hoffe es ist jetzt klarer. – agstudy

+0

Danke, es ist jetzt viel klarer. Ich würde immer noch gerne verstehen, warum meine Version nicht funktioniert. –

0

Wenn Sie setzen Sie den Variablennamen zwischen Anführungszeichen, wenn Sie die Funktion aufrufen, funktioniert es:

> b <- function(data,name) { within(data,print(name)) } 
> b(a, "x") 
[1] "x" 
    x y 
1 1 1 
2 2 2 
3 3 3 
4 4 4 
5 5 5 
6 6 6 
7 7 7 
8 8 8 
9 9 9 
10 10 10 
Verwandte Themen