case_when在mutate管道中

tom*_*omw 34 r dplyr

它似乎dplyr::case_whendplyr::mutate调用中的其他命令不同.例如:

library(dplyr)

case_when(mtcars$carb <= 2 ~ "low",
          mtcars$carb > 2 ~ "high") %>% 
  table
Run Code Online (Sandbox Code Playgroud)

作品:

.
high  low 
  15   17 
Run Code Online (Sandbox Code Playgroud)

但放入case_when一个mutate链:

mtcars %>% 
  mutate(cg = case_when(carb <= 2 ~ "low",
                        carb > 2 ~ "high"))
Run Code Online (Sandbox Code Playgroud)

你得到:

 Error: object 'carb' not found
Run Code Online (Sandbox Code Playgroud)

虽然这很好

mtcars %>% 
  mutate(cg = carb %>% 
           cut(c(0, 2, 8)))
Run Code Online (Sandbox Code Playgroud)

Geo*_*ood 49

随着版本0.7.0dplyr,case_when工作中mutate,如下所示:

library(dplyr) # >= 0.7.0
mtcars %>% 
  mutate(cg = case_when(carb <= 2 ~ "low",
                        carb > 2  ~ "high"))
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请访问:http://dplyr.tidyverse.org/reference/case_when.html

  • `dplyr` &lt; `0.7.0` 将受益于一条错误消息,表明这已在 `0.7.0` 中解决,而不是 `Error: object 'carb' not found`。 (2认同)

akr*_*run 16

我们可以用 .$

mtcars %>%  
     mutate(cg = case_when(.$carb <= 2 ~ "low",  .$carb > 2 ~ "high")) %>%
    .$cg %>%
    table()
# high  low 
#  15   17 
Run Code Online (Sandbox Code Playgroud)

  • @tomw我刚刚根据你发布的问题回答,根据Sumedh的(已删除的帖子),`case_when`仍处于试验阶段,因此一些适用于其他功能的常规事物在这里可能不起作用. (3认同)

tom*_*omw 6

感谢@sumedh:@hadley 解释说这是一个众所周知的缺点case_when:

case_when()仍然有点实验,目前不在里面工作mutate().这将在未来版本中修复.


小智 6

就我而言,准引用很有帮助。您可以提前创建一组定义突变规则的引用公式(并且可以像第一个公式一样使用已知的列名称,或者像!!第二个公式一样受益并动态创建规则),然后在mutate-case_when组合中使用,如下所示

    library(dplyr)
    library(rlang)
    pattern <- quos(gear == 3L ~ "three", !!sym("gear") == 4L ~ "four", gear == 5L ~ "five")
    # Or
    # pattern <- list(
    #     quo(gear == 3L ~ "three"), 
    #     quo(!!sym("gear") == 4L ~ "four"),
    #     quo(gear == 5L ~ "five"))
    #
    mtcars %>% mutate(test = case_when(!!!pattern)) %>% head(10L)
#>     mpg cyl  disp  hp drat    wt  qsec vs am gear carb  test
#> 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4  four
#> 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4  four
#> 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1  four
#> 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 three
#> 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 three
#> 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 three
#> 7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 three
#> 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2  four
#> 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2  four
#> 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4  four
Run Code Online (Sandbox Code Playgroud)

我更喜欢这样的解决方案,因为它允许创建复杂的规则,例如使用map2LHS 条件和 RHS 值来生成引用的公式

    library(rlang)
    library(purrr)
    map2(c(3, 4, 5), c("three", "four", "five"), ~quo(gear == !!.x ~ !!.y))
#> [[1]]
#> <quosure>
#> expr: ^gear == 3 ~ "three"
#> env:  0000000014286520
#> 
#> [[2]]
#> <quosure>
#> expr: ^gear == 4 ~ "four"
#> env:  000000001273D0E0
#> 
#> [[3]]
#> <quosure>
#> expr: ^gear == 5 ~ "five"
#> env:  00000000125870E0
Run Code Online (Sandbox Code Playgroud)

并在不同的地方使用它,应用于不同的数据集,而无需每次需要复杂的突变时手动输入所有规则。

作为问题的最终答案,7个附加符号和两个括号解决了它

library(rlang)
library(dplyr)
mtcars %>% 
    mutate(test = case_when(!!!quos(gear == 3L ~ "three", gear != 3L ~ "not three"))) %>% 
    head(10L)
#>     mpg cyl  disp  hp drat    wt  qsec vs am gear carb      test
#> 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 not three
#> 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 not three
#> 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 not three
#> 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1     three
#> 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2     three
#> 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1     three
#> 7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4     three
#> 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 not three
#> 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 not three
#> 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4 not three
Run Code Online (Sandbox Code Playgroud)

reprex 包于 2019-01-16 创建(v0.2.1.9000)