Использовать имена переменных в функциях dplyr
Я хочу использовать имена переменных как строки в функциях dplyr
. См. Пример ниже:
df <- data.frame(
color = c("blue", "black", "blue", "blue", "black"),
value = 1:5)
filter(df, color == "blue")
Он работает отлично, но я хотел бы ссылаться на color
на строку, примерно так:
var <- "color"
filter(df, this_probably_should_be_a_function(var) == "blue").
Я был бы счастлив сделать это с помощью любых средств и с удовольствием использовать простой для чтения синтаксис dplyr
.
Ответы
Ответ 1
Для версий dplyr
[0.3 - 0.7) (? - июнь 2017 г.)
(Более свежие версии dplyr
приведены в других ответах на этот вопрос).
Начиная с dplyr 0.3
каждая функция dplyr
использующая нестандартную оценку (NSE, см. Пост релиза и виньетка), имеет стандартную близнец оценки (SE), заканчивающийся подчеркиванием. Они могут быть использованы для передачи переменных. Для filter
это будет filter_
. Используя filter_
вы можете передать логическое условие в виде строки.
filter_(df, "color=='blue'")
# color value
# 1 blue 1
# 2 blue 3
# 3 blue 4
Построить строку с логическим условием, конечно, просто
l <- paste(var, "==", "'blue'")
filter_(df, l)
Ответ 2
В более новых версиях мы можем использовать, мы можем создавать переменные в кавычках, а затем в кавычках (UQ
или !!
) для оценки
var <- quo(color)
filter(df, UQ(var) == "blue")
# color value
#1 blue 1
#2 blue 3
#3 blue 4
Из-за приоритета оператора мы можем потребовать ()
обернуть вокруг !!
filter(df, (!!var) == "blue")
# color value
#1 blue 1
#2 blue 3
#3 blue 4
С новой версией, ||
имеют более высокий приоритет, поэтому
filter(df, !! var == "blue")
должно работать (как прокомментировал @Moody_Mudskipper)
Более старый вариант
Мы также можем использовать:
filter(df, get(var, envir=as.environment(df))=="blue")
#color value
#1 blue 1
#2 blue 3
#3 blue 4
РЕДАКТИРОВАТЬ: переставил порядок решений
Ответ 3
Начиная с версии 0.7 некоторые вещи снова изменились.
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')
Более общие случаи объясняются в виньетке программирования dplyr.
Ответ 4
Часто спрашивали, но все же нет легкой поддержки afaik. Однако в отношении этой публикации:
eval(substitute(filter(df, var == "blue"),
list(var = as.name(var))))
# color value
# 1 blue 1
# 2 blue 3
# 3 blue 4
Ответ 5
Вот один из способов сделать это, используя функцию sym()
в пакете 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")
Ответ 6
новый с rlang
версией> = 0.4.0
.data
теперь распознается как способ ссылки на родительский фрейм данных, поэтому ссылка по строке работает следующим образом:
var <- "color"
filter(df, .data[[var]] == "blue")
Если переменная уже является символом, то {{}}
будет правильно разыменовывать ее
Пример 1:
var <- quo(color)
filter(df, {{var}} == "blue")
или более реалистично
f <- function(v) {
filter(df, {{v}} == "blue")
}
f(color) # Curly-curly provides automatic NSE support