J'ai remarqué que de nombreux packages vous permettent de passer des noms de symboles qui peuvent même ne pas être valides dans le contexte où la fonction est appelée. Je me demande comment cela fonctionne et comment je peux l'utiliser dans mon propre code?
Voici un exemple avec ggplot2:
a <- data.frame(x=1:10,y=1:10)
library(ggplot2)
qplot(data=a,x=x,y=y)
x
et y
n'existent pas dans mon espace de noms, mais ggplot comprend qu'ils font partie du bloc de données et remet leur évaluation à un contexte dans lequel ils sont valides. J'ai essayé de faire la même chose:
b <- function(data,name) { within(data,print(name)) }
b(a,x)
Cependant, cela échoue lamentablement:
Error in print(name) : object 'x' not found
Qu'est-ce que je fais mal? Comment cela marche-t-il?
Remarque : ce n'est pas un doublon de Pass variable nommer une fonction dans r
Je sais que c'est un fil plus ancien, mais c'est celui auquel j'ai fait référence dans le passé. J'ai récemment découvert ce que je pense être une meilleure approche pour passer des noms de variables. J'ai donc pensé que je l'inclurais. J'espère que ça aidera quelqu'un.
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
Mise à jour L'approche utilise une évaluation non standard. J'ai commencé à expliquer mais j'ai rapidement réalisé que Hadley Wickham le faisait beaucoup mieux que moi. Lisez ceci http://adv-r.had.co.nz/Computing-on-the-language.html
Vous pouvez le faire en utilisant match.call
par exemple:
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
explication:
match.call renvoie un appel dans lequel tous les arguments spécifiés sont spécifiés par leur nom complet.
Voici donc la sortie de match.call
est 2 symboles:
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
Alors j'utilise le premier symbole mtcars ansd convertit le second en une chaîne:
mtcars[,"cyl"]
ou équivalent à:
eval(pars$data)[,as.character(pars$name)]
Si vous mettez le nom de la variable entre guillemets lorsque vous appelez la fonction, cela fonctionne:
> 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