首页 > 解决方案 > dplyr::if_else 是否同时评估 TRUE 和 FALSE?

问题描述

考虑以下示例:

library(dplyr)

# sample data 
set.seed(1)
mydf <- data.frame(value = as.logical(sample(0:1, 15, replace = TRUE)), group = rep(letters[1:3],each = 5), index = 1:5)

# finds either index of first "TRUE" value by group, or the last value. 
# works with base::ifelse
mydf %>% group_by(group) %>% mutate(max_value = ifelse(all(!value), max(index), index[min(which(value))]))
#> # A tibble: 15 x 4
#> # Groups:   group [3]
#>    value group index   max_value
#>    <lgl> <fct> <int>      <int>
#>  1 FALSE a         1          2
#>  2 TRUE  a         2          2
#>  3 FALSE a         3          2
#>  4 FALSE a         4          2
#>  5 TRUE  a         5          2
#>  6 FALSE b         1          4
#>  7 FALSE b         2          4
#>  8 FALSE b         3          4
#>  9 TRUE  b         4          4
#> 10 TRUE  b         5          4
#> 11 FALSE c         1          5
#> 12 FALSE c         2          5
#> 13 FALSE c         3          5
#> 14 FALSE c         4          5
#> 15 FALSE c         5          5

# the same gives a warning with dplyr::if_else
mydf %>% group_by(group) %>% mutate(max_value = if_else(all(!value), max(index), index[min(which(value))]))

#> Warning in min(which(value)): no non-missing arguments to min; returning Inf

#> # A tibble: 15 x 4
#> # Groups:   group [3]
#>    value group index  max_value
#>    <lgl> <fct> <int>      <int>
#>  1 FALSE a         1          2
#>  2 TRUE  a         2          2
#>  3 FALSE a         3          2
#>  4 FALSE a         4          2
#>  5 TRUE  a         5          2
#>  6 FALSE b         1          4
#>  7 FALSE b         2          4
#>  8 FALSE b         3          4
#>  9 TRUE  b         4          4
#> 10 TRUE  b         5          4
#> 11 FALSE c         1          5
#> 12 FALSE c         2          5
#> 13 FALSE c         3          5
#> 14 FALSE c         4          5
#> 15 FALSE c         5          5

如代码中所述 -dplyr::if_else确实会导致警告

min(which(value)) 中的警告:min 没有非缺失参数;返回 Inf

删除“all FALSE”组 c - 不再警告:

mydf_allTRUE <- mydf
mydf_allTRUE[14, 'value'] <- TRUE

mydf_allTRUE %>% group_by(group) %>% mutate(max_value = if_else(all(!value), max(index), index[min(which(value))]))
#> # A tibble: 15 x 4
#> # Groups:   group [3]
#>    value group index max_value
#>    <lgl> <fct> <int>     <int>
#>  1 FALSE a         1         2
#>  2 TRUE  a         2         2
#>  3 FALSE a         3         2
#>  4 FALSE a         4         2
#>  5 TRUE  a         5         2
#>  6 FALSE b         1         4
#>  7 FALSE b         2         4
#>  8 FALSE b         3         4
#>  9 TRUE  b         4         4
#> 10 TRUE  b         5         4
#> 11 FALSE c         1         4
#> 12 FALSE c         2         4
#> 13 FALSE c         3         4
#> 14 TRUE  c         4         4
#> 15 FALSE c         5         4

reprex 包(v0.3.0)于 2019 年 12 月 22 日创建

让我感到困惑的是(我相信)我以部件 ( )必须包含值TRUE的方式构造部件。为什么这会发出警告?这是有问题的,因为我有几千组的数据,其中大部分都在“FALSE”位中,并且警告使计算非常慢。FALSEindex[min(which(value))]

我很高兴使用base::ifelse,但我只是想知道如何dplyr::if_else评估 TRUE 和 FALSE 方面,这是同时进行的吗?

标签: rdplyr

解决方案


问题是因为我们正在检查有返回NULL withwhich(value)`的组的情况

min(NULL)
#[1] Inf

警告消息:在 min(NULL) 中:min 没有非缺失参数;返回 Inf


一个选项是which通过索引来处理输出[1]以返回NA

mydf %>%
   group_by(group) %>%
   mutate(max_value = if_else(all(!value), max(index), index[which(value)[1]]))
# A tibble: 15 x 4
# Groups:   group [3]
#   value group index max_value
#   <lgl> <fct> <int>     <int>
# 1 FALSE a         1         2
# 2 TRUE  a         2         2
# 3 FALSE a         3         2
# 4 FALSE a         4         2
# 5 TRUE  a         5         2
# 6 FALSE b         1         4
# 7 FALSE b         2         4
# 8 FALSE b         3         4
# 9 TRUE  b         4         4
#10 TRUE  b         5         4
#11 FALSE c         1         5
#12 FALSE c         2         5
#13 FALSE c         3         5
#14 FALSE c         4         5
#15 FALSE c         5         5

此外,在这种情况下,由于我们返回单个元素,if/else因此会更合适

mydf %>%
    group_by(group) %>%
    mutate(max_value = if(all(!value)) max(index) else index[which(value)[1]])
# A tibble: 15 x 4
# Groups:   group [3]
#   value group index max_value
#   <lgl> <fct> <int>     <int>
# 1 FALSE a         1         2
# 2 TRUE  a         2         2
# 3 FALSE a         3         2
# 4 FALSE a         4         2
# 5 TRUE  a         5         2
# 6 FALSE b         1         4
# 7 FALSE b         2         4
# 8 FALSE b         3         4
# 9 TRUE  b         4         4
#10 TRUE  b         5         4
#11 FALSE c         1         5
#12 FALSE c         2         5
#13 FALSE c         3         5
#14 FALSE c         4         5
#15 FALSE c         5         5

推荐阅读