Case_when 不满足条件时执行代码

时间:2021-04-22 22:50:33

标签: r dplyr

Case_when 似乎即使在不满足条件时也会执行代码,见下文:

df <- tibble(
    group = c('A', 'A', 'B', 'C'),
    take_max = c(F, F, T, T),
    value = c(NA, NA, 2, 3)
)

df %>%
    group_by(group) %>%
    mutate(
        res = case_when(
            take_max ~ max(value, na.rm = T),
            TRUE ~ 1
            )
    )
    

case_when 正确计算了值,但它也会返回此警告:

Warning: Problem with `mutate()` input `res`.
ℹ no non-missing arguments to max; returning -Inf
ℹ Input `res` is `case_when(take_max ~ max(value, na.rm = T), TRUE ~ 1)`.
ℹ The warning occurred in group 1: group = "A".

为什么 case_when 甚至在“A”组的情况下计算最大值,而它不应该看到等式的右侧?

2 个答案:

答案 0 :(得分:5)

如果不评估分组设置中的右侧,您基本上无法逃脱。这是 R 的一个基本特性——在计算表达式 max(df$value, na.rm = TRUE) 之前,R 无法知道从表达式中得到什么。

有两种方法可以解决这个问题:

(1) 在单个组上运行表达式,而不是通过一次运行所有组的 group_by

(2) 为 max 制作一个简单的包装函数:

SafeMax <- function(x) if (all(is.na(x))) NA_real_ else max(x, na.rm = TRUE)

并使用它代替 max(., na.rm=TRUE)

答案 1 :(得分:2)

package hablar 具有 @MichaelChirico 的回答中提到的 SafeMax 实现。

library(dplyr)

df %>%
  group_by(group) %>%
  mutate(
    res = case_when(
      take_max ~ as.numeric(hablar::max_(value)),
      TRUE ~ as.numeric(1)
    )
  ) %>% ungroup

#  group take_max value   res
#  <chr> <lgl>    <dbl> <dbl>
#1 A     FALSE       NA     1
#2 A     FALSE       NA     1
#3 B     TRUE         2     2
#4 C     TRUE         3     3