dplyr if_else()vs base R ifelse()

sta*_*tor 15 if-statement r dplyr

我在Tidyverse中相当熟练,但总是使用ifelse()而不是dplyr if_else().我想切换此行为,并默认为始终使用dplyr::if_else()和弃用ifelse()我的代码.

有什么理由不这样做吗?这可能会让我陷入困境吗?我会饶有你的细节,但最近,if_else()当我在数据分析中不知不觉地创建了一列字符矩阵时,并没有使用我.如果我切换到总是使用if_else()我希望将来避免这个问题.

Jam*_*mes 17

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
Run Code Online (Sandbox Code Playgroud)


Tun*_*ung 10

另一个原因选择if_elseifelse是,ifelseDatenumeric对象

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
Run Code Online (Sandbox Code Playgroud)

if_else也快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"
Run Code Online (Sandbox Code Playgroud)

reprex包创建于2018-06-01(v0.2.0).


Joe*_*Joe 5

我还要添加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
Run Code Online (Sandbox Code Playgroud)

  • 回答@stackinator:基本等效项是`ifelse(is.na(val),9,ifelse(val &lt;100,1,2))`。 (3认同)
  • 你怎么能用基础 R `ifelse()` 来添加 `missing = 9` 来实现这一点?你的代码有点不对劲。它应该是`if_else(value &lt; 100, 1, 2, missing = 9)`。 (2认同)

Chr*_*isW 5

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
Run Code Online (Sandbox Code Playgroud)

与之比较

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

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