R 不满足条件时执行代码时的情况

R 不满足条件时执行代码时的情况,r,dplyr,R,Dplyr,Case\u当似乎在不满足条件的情况下执行代码时,请参见以下内容: 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(va

Case\u当
似乎在不满足条件的情况下执行代码时,请参见以下内容:

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\u当
甚至在组“A”的情况下计算最大值时,它不应该看到等式的右侧?

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

有两种解决方法:

(1) 在单个组上运行表达式,而不是通过同时运行所有组的
group\u by

(2) 为
max
创建一个简单的包装函数:

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

SafeMaxpackage
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 
库(dplyr)
df%>%
分组依据(分组)%>%
变异(
res=情况(
将_max~as.numeric(hablar::max_(value)),
TRUE~as.numeric(1)
)
)%%>%解组
#组获取最大值res
#        
#1一个假NA 1
#2 A错误的NA 1
#3 B真实的2 2
#4 C真实的3 3

请参见
帮助页中的示例。有一条注释说,“case_when()计算所有RHS表达式,然后通过提取所选(通过LHS表达式)部分来构造其结果。”
case_when
不会有条件地计算表达式,它只是有条件地返回不同的值。谢谢——我想我对R的评价方法还有很多要理解。当计算第i行时,我们查看第一个逻辑条件(即,
take_max[i]
)。如果它是
TRUE
,我们查看相应表达式的
i
th值,
max(value,na.rm=TRUE)[i]
,或者第一个值,如果它是标量(我们循环使用)。问题是,在计算之前,通常无法知道表达式的
i
th值可能是什么。
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