【问题标题】:dplyr if_else() vs base R ifelse()dplyr if_else() 与基础 R ifelse()
【发布时间】:2018-11-11 18:08:06
【问题描述】:

我对 Tidyverse 相当精通,但一直使用 ifelse() 而不是 dplyr if_else()。我想切换此行为并默认始终使用 dplyr::if_else() 并从我的代码中弃用 ifelse()

有什么理由不这样做吗?这可能会给我带来麻烦吗?我会为您省去细节,但最近,当我在数据分析中不知不觉地创建了一列字符矩阵时,不使用if_else() 把我搞砸了。如果我切换到始终使用if_else(),我希望以后能避免这个问题。

【问题讨论】:

标签: r if-statement dplyr


【解决方案1】:

if_else 更严格。它检查两个备选方案是否属于同一类型,否则会引发错误,而ifelse 将根据需要提升类型。在某些情况下这可能是一个好处,但如果您不检查错误或明确强制类型转换,则可能会破坏脚本。例如:

ifelse(c(TRUE,TRUE,FALSE),"a",3)
[1] "a" "a" "3"
if_else(c(TRUE,TRUE,FALSE),"a",3)
Error: `false` must be type character, not double

【讨论】:

    【解决方案2】:

    选择if_else 而不是ifelse 的另一个原因是ifelseDate 变成numeric 对象

    Dates <- as.Date(c('2018-10-01', '2018-10-02', '2018-10-03'))
    new_Dates <- ifelse(Dates == '2018-10-02', Dates + 1, Dates)
    str(new_Dates)
    
    #>  num [1:3] 17805 17807 17807
    

    if_else is also faster than ifelse

    请注意,在测试多个条件时,如果我们使用case_when,代码将更具可读性且不易出错。

    library(dplyr)
    
    case_when(
      Dates == '2018-10-01' ~ Dates - 1,
      Dates == '2018-10-02' ~ Dates + 1,
      Dates == '2018-10-03' ~ Dates + 2,
      TRUE ~ Dates
    )
    
    #> [1] "2018-09-30" "2018-10-03" "2018-10-05"
    

    reprex package (v0.2.0) 于 2018 年 6 月 1 日创建。

    【讨论】:

    • if_elsecase_when 对于一种情况有什么区别?
    • 不回答我的问题。
    【解决方案3】:

    我还要补充一点,if_else() 可以在 NA 的情况下赋予一个值,这是添加额外条件的便捷方式。

    df <- data_frame(val = c(80, 90, NA, 110))
    df %>% mutate(category = if_else(val < 100, 1, 2, missing = 9))
    
    #     val category
    #   <dbl>    <dbl>
    # 1    80        1
    # 2    90        1
    # 3    NA        9
    # 4   110        2
    

    【讨论】:

    • 如何使用基本 R ifelse() 添加 missing = 9 来完成此操作?而且你的代码有点不对劲。应该是if_else(value &lt; 100, 1, 2, missing = 9)
    • 回答@stackinator:基本等价物是ifelse(is.na(val), 9, ifelse(val &lt; 100, 1, 2))
    • 这个项目之后我开始使用if_else,干净、整洁、简洁...github.com/englianhu/binary.com-interview-question/blob/master/…
    【解决方案4】:

    选择if_else() 而不是ifelse() 的另一个重要原因是检查长度的一致性。看到这个危险的陷阱:

    > tibble(x = 1:3, y = ifelse(TRUE, x, 4:6))
    # A tibble: 3 x 2
          x     y
      <int> <int>
    1     1     1
    2     2     1
    3     3     1
    

    比较

    > tibble(x = 1:3, y = if_else(TRUE, x, 4:6))
        Error: `true` must be length 1 (length of `condition`), not 3.
    

    根据单个(标量)逻辑变量的值,这两种情况的意图显然是使列y 等于x 或等于4:6ifelse() 静默将其输出截断为长度 1,然后静默回收。 if_else() 从源头捕获几乎可以肯定的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 2016-06-28
      • 1970-01-01
      • 1970-01-01
      • 2019-12-11
      相关资源
      最近更新 更多