【问题标题】:case_when in mutate pipecase_when 在变异管道中
【发布时间】:2016-12-03 14:57:06
【问题描述】:

似乎dplyr::case_when 的行为与dplyr::mutate 调用中的其他命令不同。例如:

library(dplyr)

case_when(mtcars$carb <= 2 ~ "low",
          mtcars$carb > 2 ~ "high") %>% 
  table

作品:

.
high  low 
  15   17 

但是将case_when 放入mutate 链中:

mtcars %>% 
  mutate(cg = case_when(carb <= 2 ~ "low",
                        carb > 2 ~ "high"))

你会得到:

 Error: object 'carb' not found

虽然这很好用

mtcars %>% 
  mutate(cg = carb %>% 
           cut(c(0, 2, 8)))

【问题讨论】:

  • 是的,不会。检查case_whenherethis上的部分
  • 如下所述,这个问题已经随着 dplyr > 0.7.0 消失了
  • 也许接受其中一个答案,看起来现在可以了。
  • 如果您想将一个范围划分为多个区间,值得考虑使用cut 而不是case_whencut 有一个 labels 参数,可以重命名结果类别。

标签: r dplyr


【解决方案1】:

dplyr0.7.0 版本开始,case_whenmutate 中工作如下:

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

欲了解更多信息:http://dplyr.tidyverse.org/reference/case_when.html

【讨论】:

【解决方案2】:

我们可以使用.$

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

【讨论】:

  • 当然,我对. 运算符很熟悉,但cutrecode 等则不需要...
  • @tomw 我只是根据您发布的问题回答,根据 Sumedh 的(已删除帖子),case_when 仍处于实验阶段,因此一些常规的东西适用于其他功能在这里可能行不通。
【解决方案3】:

感谢@sumedh:@hadley has explained,这是case_when 的一个已知缺点:

case_when() 仍处于试验阶段,目前无法使用 里面mutate()。这将在未来的版本中修复。

【讨论】:

    【解决方案4】:

    就我而言,准报价帮助很大。您可以提前创建一组引用的公式来定义变异规则(或者使用第一个公式中的已知列名,或者从!! 中受益并像第二个公式中那样动态创建规则),然后在 @ 987654323@ - 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
    

    我更喜欢这样的解决方案,因为它允许创建复杂的规则,例如使用 map2 与 LHS 条件和 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
    

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

    作为问题的最终答案,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
    

    reprex package (v0.2.1.9000) 于 2019 年 1 月 16 日创建

    【讨论】:

      【解决方案5】:
      library(dplyr) #loading the dplyr package
      
      content150_fortified <- content150 %>% #creating a new variable
      mutate(number_yn = case_when( #creating a new column using mutate
              number >= 18 & number <=25 ~ "no", # if number is "none", make number_yn "no"
              number!="none" ~ "yes"  # if number is not "none", make number_yn "yes"
              )
            )
      

      【讨论】:

      • 好的,我会尝试一些不同的
      【解决方案6】:

      除了上面@akrun 的回答,请注意case_when() 的右括号不能单独放在一行。

      例如,这可以正常工作:

      mtcars %>%  
         mutate(cg = case_when(
            .$carb <= 2 ~ "low",  .$carb > 2 ~ "high")) 
      

      但事实并非如此:

      mtcars %>%  
         mutate(cg = case_when(
            .$carb <= 2 ~ "low",  .$carb > 2 ~ "high")
            ) 
      

      【讨论】:

      • 嗯?两者都适合我。我无法想象 解析器 会遇到这样的问题(与底层评估器相反)。
      猜你喜欢
      • 1970-01-01
      • 2020-06-07
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      • 1970-01-01
      • 2017-09-27
      • 2023-03-29
      • 2021-12-10
      相关资源
      最近更新 更多