web-dev-qa-db-fra.com

Passer un nom de variable à une fonction dans R

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

27
static_rtti

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

25
Jacob H

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)]
13
agstudy

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
3
Waldir Leoncio