在 dplyr 动词中将字符串作为参数传递
Posted
技术标签:
【中文标题】在 dplyr 动词中将字符串作为参数传递【英文标题】:Passing strings as arguments in dplyr verbs 【发布时间】:2014-08-28 11:15:11 【问题描述】:我希望能够为 dplyr
动词定义参数
condition <- "dist > 50"
然后在dplyr
函数中使用这些字符串:
require(ggplot2)
ds <- cars
ds1 <- ds %>%
filter (eval(condition))
ds1
但是会报错
Error: filter condition does not evaluate to a logical vector.
代码应为:
ds1<- ds %>%
filter(dist > 50)
ds1
导致:
ds1
speed dist
1 14 60
2 14 80
3 15 54
4 18 56
5 18 76
6 18 84
7 19 68
8 20 52
9 20 56
10 20 64
11 22 66
12 23 54
13 24 70
14 24 92
15 24 93
16 24 120
17 25 85
问题:
如何将字符串作为参数传递给dplyr
动词?
【问题讨论】:
据我了解,这是work in progress 现在它已经完成并且是标准dplyr
安装的一部分。
【参考方案1】:
由于这些 2014 年的答案,使用 rlang's quasiquotation 有两种新方法。
常规硬编码过滤语句。为了比较,语句dist > 50
直接包含在dplyr::filter()
中。
library(magrittr)
# The filter statement is hard-coded inside the function.
cars_subset_0 <- function( )
cars %>%
dplyr::filter(dist > 50)
cars_subset_0()
结果:
speed dist
1 14 60
2 14 80
3 15 54
4 18 56
...
17 25 85
带有 NSE(非标准评估)的 rlang 方法。 如 Programming with dplyr 小插图中所述,dist > 50
语句由 rlang::enquo()
处理,它“使用一些黑魔法来查看参数,查看用户键入的内容,并将该值作为 quosure 返回”。然后 rlang 的 !!
取消引用输入“以便在周围的上下文中立即对其进行评估”。
# The filter statement is evaluated with NSE.
cars_subset_1 <- function( filter_statement )
filter_statement_en <- rlang::enquo(filter_statement)
message("filter statement: `", filter_statement_en, "`.")
cars %>%
dplyr::filter(!!filter_statement_en)
cars_subset_1(dist > 50)
结果:
filter statement: `~dist > 50`.
<quosure>
expr: ^dist > 50
env: global
speed dist
1 14 60
2 14 80
3 15 54
4 18 56
17 25 85
rlang 方法传递字符串。 语句 "dist > 50"
作为显式字符串传递给函数,并由 rlang::parse_expr()
解析为表达式,然后由 !!
取消引用。 p>
# The filter statement is passed a string.
cars_subset_2 <- function( filter_statement )
filter_statement_expr <- rlang::parse_expr(filter_statement)
message("filter statement: `", filter_statement_expr, "`.")
cars %>%
dplyr::filter(!!filter_statement_expr)
cars_subset_2("dist > 50")
结果:
filter statement: `>dist50`.
speed dist
1 14 60
2 14 80
3 15 54
4 18 56
...
17 25 85
dplyr::select()
让事情变得更简单。显式字符串只需要!!
。
# The select statement is passed a string.
cars_subset_2b <- function( select_statement )
cars %>%
dplyr::select(!!select_statement)
cars_subset_2b("dist")
【讨论】:
【参考方案2】:在 dplyr 的下一个版本中,它可能会这样工作:
condition <- quote(dist > 50)
mtcars %>%
filter_(condition)
【讨论】:
等不及了。 dplyr 的直观性和智能性一直让我感到惊讶。谢谢,哈德利! 如果想要传递多个参数怎么办?传递像list("dist > 50", "speed > 10")
这样的列表会返回Error: Can't convert a list to a quosure
编辑:找到它:paste(list('dist > 50', 'speed > 10'), collapse=" & ")
【参考方案3】:
虽然他们正在努力,但这里有一个使用if
的解决方法:
library(dplyr)
library(magrittr)
ds <- data.frame(attend = c(1:5,NA,7:9,NA,NA,12))
filter_na <- FALSE
filtertest <- function(x,filterTF = filter_na)
if(filterTF) x else !(x)
ds %>%
filter(attend %>% is.na %>% filtertest)
attend
1 1
2 2
3 3
4 4
5 5
6 7
7 8
8 9
9 12
filter_na <- TRUE
ds %>%
filter(attend %>% is.na %>% filtertest)
attend
1 NA
2 NA
3 NA
【讨论】:
谢谢,@AndrewMacDonald!抱歉,之前没有提供可重现的示例 太好了,谢谢@AndrewMacDonald,这很有效,而且最重要的是给了我一个使用 dplyr 函数的简单例子——我想参考一下。再次感谢! 很高兴它有用!我在上面稍微编辑了一下(不应该在filter
中使用$
!
我不知道 $ 也没有注意到故障(或者没有意识到这是由于这个原因?)。感谢您的提醒,我会记住这一点。以上是关于在 dplyr 动词中将字符串作为参数传递的主要内容,如果未能解决你的问题,请参考以下文章
如何在 CloudFormation 中将字符串列表作为参数传递?
如何在 django 2 中将 url 中的 # 作为参数传递