【问题标题】:Nested `if_else()` and `is.na()` logic inconsistency?嵌套的 `if_else()` 和 `is.na()` 逻辑不一致?
【发布时间】:2019-02-06 11:55:15
【问题描述】:

我正在尝试使用mutateif_else() 来获得将以下逻辑语句应用于数据框的两列的结果:

如果在 a 或 b 中为 Yes,则为 NA,如果两者都为 NA,如果两者都为 No 或 No & NA,则为 FALSE

library(magrittr)
library(dplyr)

data.frame(
    "a"=c(NA,"No","Yes","Yes","No","No",NA),
    "b"=c(NA,"No","Yes","No","Yes",NA,"No")
) %>% 
mutate(
    logical = if_else(
        a == "Yes" | b == "Yes",
        TRUE,
        if_else(
            is.na(a) & is.na(b),
            NA,
            FALSE
        )
    )
)
#>      a    b logical
#> 1 <NA> <NA>      NA
#> 2   No   No   FALSE
#> 3  Yes  Yes    TRUE
#> 4  Yes   No    TRUE
#> 5   No  Yes    TRUE
#> 6   No <NA>      NA
#> 7 <NA>   No      NA

在最后两行中,我得到 NA 而不是预期结果 FALSE。预期,因为is.na(a) &amp; is.na(b) 应该返回 FALSE,如下例所示。

# False as expected here
if_else(is.na(NA) & is.na("No"),NA,FALSE)
#> [1] FALSE

我是否错过了 if_else 的工作方式?

reprex package (v0.2.1) 于 2019 年 2 月 6 日创建

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    你也可以这样做:

    library(dplyr)
    
    data.frame(
      "a"=c(NA,"No","Yes","Yes","No","No",NA),
      "b"=c(NA,"No","Yes","No","Yes",NA,"No")
    ) %>%
      mutate(
        logical = case_when(
          a == "Yes" | b == "Yes" ~ TRUE,
          is.na(a) & is.na(b) ~ NA,
          TRUE ~ FALSE
        )
      )
    

    输出:

         a    b logical
    1 <NA> <NA>      NA
    2   No   No   FALSE
    3  Yes  Yes    TRUE
    4  Yes   No    TRUE
    5   No  Yes    TRUE
    6   No <NA>   FALSE
    7 <NA>   No   FALSE
    

    【讨论】:

    • 我同意这是一个更具可读性的解决方案,我不知道 case_when 看起来非常有用,但是,@akrun 的回答清楚地说明了为什么我正在做的事情不起作用。
    • 我知道,没问题;他的回答适合这个问题。但是,我个人的看法是,如果您使用的是dplyr,嵌套的ifelseif_else 意义不大,因此我总是尝试以这种方式回答——很高兴它对您了解@ 有所帮助987654327@!
    【解决方案2】:

    我们需要在第一个if_else 中添加条件来处理NA 元素,否则,与NA 元素的比较返回NA

    df1 %>% 
       mutate(logical = if_else((a == "Yes" & !is.na(a)) |
                (b == "Yes" & !is.na(b)), TRUE, 
          if_else(is.na(a) & is.na(b), NA, FALSE )))
    #     a    b logical
    #1 <NA> <NA>      NA
    #2   No   No   FALSE
    #3  Yes  Yes    TRUE
    #4  Yes   No    TRUE
    #5   No  Yes    TRUE
    #6   No <NA>   FALSE
    #7 <NA>   No   FALSE
    

    注意:在这里,我们正在尝试解决 OP 的根本问题


    此外,我们可以将== 替换为%in%NA 问题将得到解决

    df1 %>%
       mutate(logical = if_else(a %in% "Yes" | b %in% "Yes", TRUE, 
                        if_else(is.na(a) & is.na(b), NA, FALSE)))
    

    或使用base R

    replace((rowSums(df1 == "Yes", na.rm = TRUE) > 0), rowSums(is.na(df1) == 2, NA)
    #[1]    NA FALSE  TRUE  TRUE  TRUE FALSE FALSE
    

    数据

    df1 <- data.frame(
     "a"=c(NA,"No","Yes","Yes","No","No",NA),
     "b"=c(NA,"No","Yes","No","Yes",NA,"No")
       )
    

    【讨论】:

      猜你喜欢
      • 2019-01-13
      • 2016-08-08
      • 1970-01-01
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多