与NA匹配的值-缺少值-使用mutate

时间:2019-06-17 16:21:36

标签: r dplyr

我有些困惑。在mutate中将NA视为“真实值”,是否有比下面更好的方法来进行值匹配?

library(dplyr)

data_foo <- data.frame(A= c(1:2, NA, 4, NA), B = c(1, 3, NA, NA, 4))

不是所需的输出:

data_foo %>% mutate(irr = A==B)

#>    A  B   irr
#> 1  1  1  TRUE
#> 2  2  3 FALSE
#> 3 NA NA    NA
#> 4  4 NA    NA
#> 5 NA  4    NA

data_foo %>% rowwise() %>% mutate(irr = A%in%B)

#> Source: local data frame [5 x 3]
#> Groups: <by row>
#> 
#> # A tibble: 5 x 3
#>       A     B irr  
#>   <dbl> <dbl> <lgl>
#> 1     1     1 TRUE 
#> 2     2     3 FALSE
#> 3    NA    NA FALSE
#> 4     4    NA FALSE
#> 5    NA     4 FALSE

所需的输出:以下显示了所需的列irr。我正在使用这种麻烦的辅助专栏。有没有更短的方法?

data_foo %>% 
  mutate(NA_A = is.na(A), 
         NA_B = is.na(B), 
         irr = if_else(is.na(A)|is.na(B), NA_A == NA_B, A == B))

#>    A  B  NA_A  NA_B   irr
#> 1  1  1 FALSE FALSE  TRUE
#> 2  2  3 FALSE FALSE FALSE
#> 3 NA NA  TRUE  TRUE  TRUE
#> 4  4 NA FALSE  TRUE FALSE
#> 5 NA  4  TRUE FALSE FALSE

4 个答案:

答案 0 :(得分:5)

使用map2

library(tidyverse)
data_foo %>%
   mutate(irr = map2_lgl(A, B, `%in%`))
#   A  B   irr
#1  1  1  TRUE
#2  2  3 FALSE
#3 NA NA  TRUE
#4  4 NA FALSE
#5 NA  4 FALSE

或与setequal

data_foo %>% 
   rowwise %>%
   mutate(irr = setequal(A, B))

上面的方法很简洁,但是也很麻烦。我们可以将NA替换为其他值,然后执行==

data_foo %>%
     mutate_all(list(new = ~ replace_na(., -999))) %>%
     transmute(A, B, irr = A_new == B_new)
#   A  B   irr
#1  1  1  TRUE
#2  2  3 FALSE
#3 NA NA  TRUE
#4  4 NA FALSE
#5 NA  4 FALSE

或者使用bind_colsreduce

data_foo %>%
    mutate_all(replace_na, -999) %>% 
    reduce(`==`) %>% 
    bind_cols(data_foo, irr = .)

答案 1 :(得分:3)

也许比akrun's answer更简单?
以下两种方式中的任何一种都会产生预期的结果。请注意,as.character不会这样做,因为as.character(NA)的返回值为NA_character_

data_foo %>%
  mutate(irr = paste(A) == paste(B))

data_foo %>%
  mutate(irr = sQuote(A) == sQuote(B))

#Source: local data frame [5 x 3]
#Groups: <by row>
#
## A tibble: 5 x 3
#      A     B irr  
#  <dbl> <dbl> <lgl>
#1     1     1 TRUE 
#2     2     3 FALSE
#3    NA    NA TRUE 
#4     4    NA FALSE
#5    NA     4 FALSE

编辑。

  1. 在下面的注释之后,我更新了代码,现在它遵循akrun的建议。
  2. tmfmnk's answer中也有一个很棒的主意。我使用另一种类似的方法来解决问题的问题。

all.equal的文档中说

  

请勿在{{1​​}}表达式中直接使用all.equal-两者都应使用   ifisTRUE(all.equal(....))(如果适用)。

尽管identical中没有if表达式,但我认为它比mutate更稳定,并且如果比较的值是(实际上)相等。

identical

答案 2 :(得分:2)

也可能是这样:

data_foo %>%
 rowwise() %>%
 mutate(irr = identical(A, B)) %>%
 ungroup()

      A     B irr  
  <dbl> <dbl> <lgl>
1     1     1 TRUE 
2     2     3 FALSE
3    NA    NA TRUE 
4     4    NA FALSE
5    NA     4 FALSE

答案 3 :(得分:1)

如果要在值为NA时执行操作,则合并功能很有用

data_foo %>% 
  mutate(irr = coalesce(A == B, is.na(A) & is.na(B)))

#    A  B   irr
# 1  1  1  TRUE
# 2  2  3 FALSE
# 3 NA NA  TRUE
# 4  4 NA FALSE
# 5 NA  4 FALSE

> 2列相同

data_foo %>% 
  mutate(irr = coalesce(reduce(., `==`), rowMeans(is.na(.)) == 1))