在dplyr的函数中使用变量名

kub*_*uba 38 r r-faq dplyr rlang

我想在函数中使用变量名作为字符串dplyr.请参阅以下示例:

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

它工作得很好,但我想color通过字符串来引用,类似这样:

var <- "color"
filter(df, this_probably_should_be_a_function(var) == "blue").
Run Code Online (Sandbox Code Playgroud)

我很高兴,无论如何都要这样做,并且非常乐意使用易于阅读的dplyr语法.

Mar*_*ann 27

对于使用非标准评估的dplyr每个dplyr函数(NSE,请参见 发布帖子插图),有一个标准评估(SE)双尾以下划线结尾.这些可用于传递变量.因为dplyr 0.3它会dplyr.使用filter您可以将逻辑条件作为字符串传递.

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

#   color value
# 1  blue     1
# 2  blue     3
# 3  blue     4
Run Code Online (Sandbox Code Playgroud)

构造具有逻辑条件的字符串当然是直截了当的

l <- paste(var, "==",  "'blue'")
filter_(df, l)
Run Code Online (Sandbox Code Playgroud)


akr*_*run 26

您也可以使用:

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

更新

在2017年4月UQ发布的即将发布的devel版本中!!,我们可以创建引用的变量,然后取消引用(()!!)进行评估

filter(df, (!!var) == "blue")
#   color value
#1  blue     1
#2  blue     3
#3  blue     4
Run Code Online (Sandbox Code Playgroud)

由于运算符优先级,我们可能需要||回绕UQ

filter(df, !! var == "blue")
Run Code Online (Sandbox Code Playgroud)

  • 现在 `!!` 具有更高的优先级,不再需要括号 (2认同)

tak*_*kje 17

从dplyr 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')
Run Code Online (Sandbox Code Playgroud)

dplyr编程插图中解释了更一般的情况.

  • 谢谢.这是我一直在寻找的答案.这对我来说就像dplyr的混乱方向一样.我花了很长时间来解析和理解"quo"和"enquo"在这里做了什么.我可以想象我也不会是唯一的一个,这就像一个非常先进的代码片段,就像在LISP中编写宏一样.我喜欢宏和的Lisp,但我不知道他们是每个人的口味,尤其是用于编写较为简单的功能操作tibbles. (3认同)

Ben*_*ker 10

rlang版本 >= 0.4.0

.data 现在被认为是引用父数据框的一种方式,因此按字符串引用的工作方式如下:

var <- "color"
filter(df, .data[[var]] == "blue")
Run Code Online (Sandbox Code Playgroud)

如果变量已经是一个符号,那么{{}}将正确地解引用它

示例 1:

var <- quo(color)
filter(df, {{var}} == "blue")
Run Code Online (Sandbox Code Playgroud)

或更现实地

f <- function(v) {
    filter(df, {{v}} == "blue")
}
f(color) # Curly-curly provides automatic NSE support
Run Code Online (Sandbox Code Playgroud)


luk*_*keA 7

经常被问到,但仍然没有简单的支持afaik.但是,关于这个帖子:

eval(substitute(filter(df, var == "blue"), 
                list(var = as.name(var))))
#   color value
# 1  blue     1
# 2  blue     3
# 3  blue     4
Run Code Online (Sandbox Code Playgroud)


Tom*_*oth 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")
Run Code Online (Sandbox Code Playgroud)


lle*_*lls 5

上面的几个解决方案对我不起作用。现在有as.symbol函数,我们将其包装在!!. 似乎有点简单,有点。

set.seed(123)

df <- data.frame( 
  color = c("blue", "black", "blue", "blue", "black"), 
  shape = c("round", "round", "square", "round", "square"),
  value = 1:5)
Run Code Online (Sandbox Code Playgroud)

现在,将其通过输入变量作为串入dplyr功能as.symbol()!!

var <- "color"
filter(df, !!as.symbol(var) == "blue")

#   color  shape value
# 1  blue  round     1
# 2  blue square     3
# 3  blue  round     4

var <- "shape"
df %>% group_by(!!as.symbol(var)) %>% summarise(m = mean(value))

#   shape      m
#   <fct>  <dbl>
# 1 round   2.33
# 2 square  4
Run Code Online (Sandbox Code Playgroud)


lle*_*lls 5

更新。新版本dplyr1.0.0具有一些出色的新功能,使解决此类问题变得更加容易。您可以在新软件包随附的“编程”小插图中阅读相关内容。

基本上,该.data[[foo]]函数允许您更轻松地将字符串传递到函数中。

所以你可以这样做

filtFunct <- function(d, var, crit) {
filter(d, .data[[var]] %in% crit)
}

filtFunct(df, "value", c(2,4))

#   color value
# 1 black     2
# 2  blue     4

filtFunct(df, "color", "blue")

#   color value
# 1  blue     1
# 2  blue     3
# 3  blue     4
Run Code Online (Sandbox Code Playgroud)