Вложенные логические несоответствия между if_else () и is.na ()? - PullRequest
0 голосов
/ 06 февраля 2019

Я пытаюсь использовать mutate и if_else(), чтобы получить результат следующего логического утверждения, примененного к двум столбцам фрейма данных:

True, если Да в a или b, NA, если NAв обоих случаях FALSE, если оба значения: Нет или Нет & NA

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) & 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 пакетом представьте (v0.2.1)

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Вы также можете сделать:

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
0 голосов
/ 06 февраля 2019

Нам нужно добавить условие в первые 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

ПРИМЕЧАНИЕ: здесьмы пытаемся решить основную проблему ОП


Также мы можем заменить == на %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

data

df1 <- data.frame(
 "a"=c(NA,"No","Yes","Yes","No","No",NA),
 "b"=c(NA,"No","Yes","No","Yes",NA,"No")
   )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...