以编程方式使用dplyr :: case_when参数

Rob*_*ura 7 r dplyr rlang

我希望能够以编程方式使用dplyr's case_when来替换基本R cut()函数.

目前,case_when可以通过NSE与外部参数一起使用,如:

library(dplyr)
library(rlang)

patterns <- list(
  x <= 2 ~ "<=2",
  x <= 4 ~ "2<->4",
  x > 4 ~ ">4"
 )
 x <- 1:10
 case_when(!!!patterns)
Run Code Online (Sandbox Code Playgroud)

我想要做的是:在变异中使用另一个变量

这个想法会是这样的,虽然我无法弄清楚如何让它工作:

library(dplyr)
patterns_lazy <- list(
  !!quo(x) <= 2 ~ "<=2",
  !!quo(x) <= 4 ~ "2<->4",
  !!quo(x) > 4 ~ ">4"
)
x <- "cyl"
mtcars %>% mutate(ABC = case_when(!!!patterns_lazy))
Run Code Online (Sandbox Code Playgroud)

我希望能够定义我想要过滤的列(在字符串内),并检索这样的东西(这个例子不起作用,因为它是所需的语法):

x <- "cyl"
mtcars %>%
  select(cyl) %>%
  mutate(ABC = case_when(!!!patterns_lazy)) %>%
  head()

  cyl ABC
1   6 >4
2   6 >4
3   4 2<->4
4   6 >4
5   8 >4
6   6 >4
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助 :)

Lio*_*nry 10

你不能!!在那里使用:

patterns <- list(
  !!quo(x) <= 2 ~ "<=2",
  !!quo(x) <= 4 ~ "2<->4",
  !!quo(x) > 4 ~ ">4"
)
Run Code Online (Sandbox Code Playgroud)
  1. 既不支持list()也不~支持准范式.
  2. 如果它确实支持quasiquotation,则需要注意运算符优先级并将!!quo()括号括起来.
  3. 最后,这个引用x将评估为一个字符串,你将比较数字与字符串(在你的例子中将是"cyl),由于隐式强制,R将会愉快地做到:/

所以,你需要使用exprs()的替代list(),并使用x.data代词代替的报价x.

exprs()将创建一个未评估的表达式列表.未评估是好的:如果您的公式被评估,它将带有一个环境(这里是全局环境),并且该环境不包含提供给dplyr的任何数据,特别是没有.data 代词.另一方面,如果公式是"无上下文",则在数据上下文中对它们进行评估,这是我们想要的.

patterns_lazy <- exprs(
  .data[[x]] <= 2 ~ "<=2",
  .data[[x]] <= 4 ~ "2<->4",
  .data[[x]] > 4 ~ ">4"
)

x <- "cyl"
pull(mutate(mtcars, case_when(!!!patterns_lazy)))
#>  [1] ">4"    ">4"    "2<->4" ">4"    ">4"    ">4"    ">4"    "2<->4" "2<->4"
#> [10] ">4"    ">4"    ">4"    ">4"    ">4"    ">4"    ">4"    ">4"    "2<->4"
#> [19] "2<->4" "2<->4" "2<->4" ">4"    ">4"    ">4"    ">4"    "2<->4" "2<->4"
#> [28] "2<->4" ">4"    ">4"    ">4"    "2<->4"
Run Code Online (Sandbox Code Playgroud)