Réponse de Tung y Réponse de mgrund présenté évaluation ordonnée . Dans cette réponse, je montrerai comment nous pouvons utiliser ces concepts pour faire quelque chose de similaire à réponse de joran (notamment sa fonction new_column3
). L'objectif est de faciliter la compréhension des différences entre l'évaluation de base et l'évaluation ordonnée, ainsi que des différentes syntaxes qui peuvent être utilisées dans l'évaluation ordonnée. Vous aurez besoin de rlang
y dplyr
pour cela.
Utilisation d'outils d'évaluation de la base (réponse de Joran) :
new_column3 <- function(df,col_name,expr){
col_name <- deparse(substitute(col_name))
df[[col_name]] <- eval(substitute(expr),df,parent.frame())
df
}
Dans la première ligne, substitute
nous fait évaluer col_name
comme une expression, plus précisément un symbole (aussi parfois appelé un nom), et non un objet. Les substituts de rlang peuvent être :
-
ensym
- le transforme en symbole ;
-
enexpr
- le transforme en expression ;
-
enquo
- la transforme en une quosure, une expression qui indique également l'environnement dans lequel R doit chercher les variables pour l'évaluer.
La plupart du temps, vous voulez avoir ce pointeur sur l'environnement. Lorsque vous n'en avez pas spécifiquement besoin, le fait de l'avoir pose rarement des problèmes. Ainsi, la plupart du temps, vous pouvez utiliser enquo
. Dans ce cas, vous pouvez utiliser ensym
pour rendre le code plus facile à lire, car il rend plus clair ce que l'on doit faire. col_name
est.
Également dans la première ligne, deparse
consiste à transformer l'expression/le symbole en une chaîne de caractères. Vous pouvez également utiliser as.character
o rlang::as_string
.
Dans la deuxième ligne, le substitute
tourne expr
en une expression "complète" (pas un symbole), de sorte que ensym
n'est plus une option.
De même, à la deuxième ligne, nous pouvons maintenant changer eval
a rlang::eval_tidy
. Eval fonctionnerait toujours avec enexpr
mais pas avec une quosté. Lorsque vous avez une quosure, vous n'avez pas besoin de passer l'environnement à la fonction d'évaluation (comme joran l'a fait avec parent.frame()
).
Une combinaison des substitutions suggérées ci-dessus pourrait être :
new_column3 <- function(df,col_name,expr){
col_name <- as_string(ensym(col_name))
df[[col_name]] <- eval_tidy(enquo(expr), df)
df
}
Nous pouvons également utiliser la fonction dplyr
qui permettent le masquage des données (évaluation d'une colonne d'un cadre de données en tant que variable, en l'appelant par son nom). Nous pouvons changer la méthode de transformation du symbole en caractère + sous-ensemble df
en utilisant [[
con mutate
:
new_column3 <- function(df,col_name,expr){
col_name <- ensym(col_name)
df %>% mutate(!!col_name := eval_tidy(enquo(expr), df))
}
Pour éviter que la nouvelle colonne ne soit nommée "col_name", nous l'évaluons avec anxiété (par opposition à lazy-evaluate, la valeur par défaut de R) à l'aide de la commande bang-bang !!
de l'opérateur. Comme nous avons effectué une opération sur le côté gauche, nous ne pouvons pas utiliser "normal =
et doit utiliser la nouvelle syntaxe :=
.
L'opération courante qui consiste à transformer le nom d'une colonne en un symbole, puis à l'évaluer avec anxiété à l'aide de bang-bang, a un raccourci : le curly-curly. {{
de l'opérateur :
new_column3 <- function(df,col_name,expr){
df %>% mutate({{col_name}} := eval_tidy(enquo(expr), df))
}
Je ne suis pas un expert en évaluation dans R et j'ai peut-être simplifié à l'excès, ou utilisé un terme erroné, alors n'hésitez pas à me corriger dans les commentaires. J'espère avoir aidé à comparer les différents outils utilisés dans les réponses à cette question.