【问题标题】:Case_when executes code when condition is not metcase_when 在条件不满足时执行代码
【发布时间】:2021-04-22 22:50:33
【问题描述】:

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”的情况下计算最大值,而它不应该看到等式的右侧?

【问题讨论】:

  • 查看?case_when 帮助页面中的示例。有一条注释说“case_when() 计算所有 RHS 表达式,然后通过提取选定的(通过 LHS 表达式)部分来构造其结果。” case_when 不会有条件地评估表达式,它只是有条件地返回不同的值。

标签: r dplyr


【解决方案1】:

您基本上无法在分组设置中不评估右侧。这是 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)

【讨论】:

  • 谢谢——我想我对 R 的评估方法还有很多要了解的。
  • @JesseKerr 可能会考虑这一点。在评估ith 行时,我们查看第一个逻辑条件(即take_max[i])。如果它是TRUE,我们会查看对应表达式max(value, na.rm = TRUE)[i]ith 值或第一个值,如果它是标量(并且我们回收)。问题是,在评估之前,通常无法知道表达式的 ith 值可能是什么。
【解决方案2】:

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 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    相关资源
    最近更新 更多