case_when () передает NA, когда! = - PullRequest
       152

case_when () передает NA, когда! =

1 голос
/ 06 августа 2020

Я пытаюсь создать новый столбец, в котором указаны различия между двумя существующими столбцами. NA s следует считать значениями и помечать как «разница». Однако NA s "пропускаются" через компаратор !=. Я искал case_when аргументов для работы с NA s и искал альтернативные не равные компараторы, но безрезультатно.

Представление ниже показывает текущий и желаемый результат. Заранее благодарим вас за помощь!

library(dplyr)
library(tidyr)
library(tibble)

df <- 
  expand_grid(x = c("a", NA), y = c("b", NA)) %>% 
  add_row(x = "a", y = "a") %>% 
  add_row(x = "b", y = "b")

df
#> # A tibble: 6 x 2
#>   x     y    
#>   <chr> <chr>
#> 1 a     b    
#> 2 a     <NA> 
#> 3 <NA>  b    
#> 4 <NA>  <NA> 
#> 5 a     a    
#> 6 b     b

# Non-desired output: NA's passed through instead of treated as values
  df %>% 
  mutate(z = case_when(
    x == "a" & y == "a" ~ "a",
    x == "b" &  y == "b" ~ "b",
    x != y ~ "difference"
  ))
#> # A tibble: 6 x 3
#>   x     y     z         
#>   <chr> <chr> <chr>     
#> 1 a     b     difference
#> 2 a     <NA>  <NA>      
#> 3 <NA>  b     <NA>      
#> 4 <NA>  <NA>  <NA>      
#> 5 a     a     a         
#> 6 b     b     b

# Desired output
  df %>% 
  add_column(z = c(rep("difference", 3), NA_character_, "a", "b"))
#> # A tibble: 6 x 3
#>   x     y     z         
#>   <chr> <chr> <chr>     
#> 1 a     b     difference
#> 2 a     <NA>  difference
#> 3 <NA>  b     difference
#> 4 <NA>  <NA>  <NA>      
#> 5 a     a     a         
#> 6 b     b     b

Создано 06.08.2020 с помощью пакета REPEX (v0.3.0)

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Проблема связана с == и NA. Любое значение по сравнению с NA возвращает NA. Это можно исправить с помощью is.na также в сравнении, но затем это нужно повторить. Или же простое решение - изменить NA на другое значение, провести сравнение и привязать к исходному набору данных

library(dplyr)
df %>% 
   mutate(across(x:y, replace_na, '')) %>%
   transmute(z = case_when(
    x == "a" & y == "a" ~ "a",
    x == "b" &  y == "b" ~ "b",
    x != y ~ "difference"
    )) %>%
   bind_cols(df, .)
0 голосов
/ 10 августа 2020

Как упоминалось в @akrun, есть обходной путь с is.na с «исключающим или» / xor. Вот что я в итоге использовал:

df %>% 
  mutate(z = case_when(
    x == y ~ x,
    xor(is.na(x), is.na(y)) ~ "difference",
    x != y ~ "difference",
    is.na(x) & is.na(y) ~ NA_character_
  ))
...