代码之家  ›  专栏  ›  技术社区  ›  Richard J. Acton

嵌套的`if_else()`和`is.na()`逻辑不一致?

  •  1
  • Richard J. Acton  · 技术社区  · 5 年前

    我想用 mutate if_else() 要获取应用于数据帧的两列的以下逻辑语句的结果:

    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
    

    is.na(a) & is.na(b) 应返回FALSE,如下例所示。

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

    if_else 作品

    于2019-02-06由 reprex package (v0.2.1)

    2 回复  |  直到 5 年前
        1
  •  3
  •   arg0naut91    5 年前

    你也可以这样做:

    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
    
        2
  •  0
  •   akrun    5 年前

    if_else 照顾 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")
       )