web-dev-qa-db-fra.com

Utiliser des noms de variables dans les fonctions de dplyr

Je veux utiliser des noms de variables comme chaînes dans les fonctions de dplyr. Voir l'exemple ci-dessous:

df <- data.frame( 
      color = c("blue", "black", "blue", "blue", "black"), 
      value = 1:5)
filter(df, color == "blue")

Cela fonctionne parfaitement, mais je voudrais faire référence à color par chaîne, quelque chose comme ceci:

var <- "color"
filter(df, this_probably_should_be_a_function(var) == "blue").

Je serais heureux de le faire par tous les moyens et très heureux d'utiliser la syntaxe dplyr facile à lire.

37
kuba

Pour les versions dplyr [0,3 - 0,7) (? - juin 2017)

(Pour les versions dplyr plus récentes, veuillez voir les autres réponses à cette question)

À partir du dplyr 0.3 chaque dplyr fonction utilisant une évaluation non standard (NSE, voir release post et vignette ) a un jumeau d'évaluation standard (SE) se terminant par un trait de soulignement. Ceux-ci peuvent être utilisés pour transmettre des variables. Pour filter ce sera filter_. En utilisant filter_ vous pouvez passer la condition logique sous forme de chaîne.

filter_(df, "color=='blue'")

#   color value
# 1  blue     1
# 2  blue     3
# 3  blue     4

Construire la chaîne avec la condition logique est bien sûr simple

l <- paste(var, "==",  "'blue'")
filter_(df, l)
27
Mark Heckmann

Dans les versions plus récentes, nous pouvons utiliser, nous pouvons créer les variables telles que citées, puis annuler la citation (UQ ou !!) pour évaluation

var <- quo(color)
filter(df, UQ(var) == "blue")
#   color value
#1  blue     1
#2  blue     3
#3  blue     4

En raison de la priorité de l'opérateur, nous pouvons avoir besoin de () pour boucler !!

filter(df, (!!var) == "blue")
#   color value
#1  blue     1
#2  blue     3
#3  blue     4

Avec la nouvelle version, || ont une priorité plus élevée, donc

filter(df, !! var == "blue")

devrait fonctionner (comme l'a commenté @Moody_Mudskipper)

Option plus ancienne

Nous pouvons également utiliser:

 filter(df, get(var, envir=as.environment(df))=="blue")
 #color value
 #1  blue     1
 #2  blue     3
 #3  blue     4

EDIT: Réorganisé l'ordre des solutions

26
akrun

Depuis dplyr 0.7, certaines choses ont encore changé.

library(dplyr)
df <- data.frame( 
  color = c("blue", "black", "blue", "blue", "black"), 
  value = 1:5)
filter(df, color == "blue")

# it was already possible to use a variable for the value
val <- 'blue'
filter(df, color == val)

# As of dplyr 0.7, new functions were introduced to simplify the situation
col_name <- quo(color) # captures the current environment
df %>% filter((!!col_name) == val)

# Remember to use enquo within a function
filter_col <- function(df, col_name, val){
  col_name <- enquo(col_name) # captures the environment in which the function was called
  df %>% filter((!!col_name) == val)
}
filter_col(df, color, 'blue')

Des cas plus généraux sont expliqués dans la vignette de programmation dplyr .

16
takje

Souvent demandé, mais toujours pas de soutien facile afaik. Cependant, en ce qui concerne cette publication :

eval(substitute(filter(df, var == "blue"), 
                list(var = as.name(var))))
#   color value
# 1  blue     1
# 2  blue     3
# 3  blue     4
7
lukeA

Voici une façon de le faire en utilisant la fonction sym() dans le package rlang:

library(dplyr)

df <- data.frame( 
  main_color = c("blue", "black", "blue", "blue", "black"), 
  secondary_color = c("red", "green", "black", "black", "red"),
  value = 1:5, 
  stringsAsFactors=FALSE
)

filter_with_quoted_text <- function(column_string, value) {
    col_name <- rlang::sym(column_string)
    df1 <- df %>% 
      filter(UQ(col_name) == UQ(value))
    df1
}

filter_with_quoted_text("main_color", "blue")
filter_with_quoted_text("secondary_color", "red")
4
Tom Roth

nouveau avec rlang version> = 0.4.0

.data est maintenant reconnu comme un moyen de faire référence au bloc de données parent, donc la référence par chaîne fonctionne comme suit:

var <- "color"
filter(df, .data[[var]] == "blue")

Si la variable est déjà un symbole, alors {{}} le déréférencera correctement

exemple 1:

var <- quo(color)
filter(df, {{var}} == "blue")

ou plus réaliste

f <- function(v) {
    filter(df, {{v}} == "blue")
}
f(color)
1
Ben Bolker