isTRUE 和 isFALSE 在 dplyr mutate 函数中未按预期工作

Jos*_*osh 6 r dplyr

我想检查数据帧的两列中的值是否不匹配,并使用此信息创建一个新列。我想使用dplyr::mutate, 并且我希望能够处理NA值。可以使用以下代码生成一个简单的示例:

library(dplyr)
let <- c("a", "b", NA)
LET <- c("A")
perms <- expand.grid(
    let_2 =  let, 
    LET_2 =  LET, 
    let_1  =  let, 
    LET_1  =  LET, 
    stringsAsFactors = FALSE
) %>% 
    .[ncol(.):1]

> perms
  LET_1 let_1 LET_2 let_2
1     A     a     A     a
2     A     a     A     b
3     A     a     A  <NA>
4     A     b     A     a
5     A     b     A     b
6     A     b     A  <NA>
7     A  <NA>     A     a
8     A  <NA>     A     b
9     A  <NA>     A  <NA>
Run Code Online (Sandbox Code Playgroud)

然后我想检查 group 中的参数是否与1group 中的相同参数不匹配2。这是所需的输出:

> good_perms
  LET_1 let_1 LET_2 let_2 LET_mismatch let_mismatch
1     A     a     A     a        FALSE        FALSE
2     A     a     A     b        FALSE         TRUE
3     A     a     A  <NA>        FALSE         TRUE
4     A     b     A     a        FALSE         TRUE
5     A     b     A     b        FALSE        FALSE
6     A     b     A  <NA>        FALSE         TRUE
7     A  <NA>     A     a        FALSE         TRUE
8     A  <NA>     A     b        FALSE         TRUE
9     A  <NA>     A  <NA>        FALSE        FALSE
Run Code Online (Sandbox Code Playgroud)

我认为下面的代码应该可以工作,但它给出以下输出:

good_perms1 <- perms %>% 
    dplyr::mutate(LET_mismatch = !isTRUE(LET_1 == LET_2)) %>% 
    dplyr::mutate(let_mismatch = !isTRUE(let_1 == let_2)) 

> good_perms1
  LET_1 let_1 LET_2 let_2 LET_mismatch let_mismatch
1     A     a     A     a         TRUE         TRUE
2     A     a     A     b         TRUE         TRUE
3     A     a     A  <NA>         TRUE         TRUE
4     A     b     A     a         TRUE         TRUE
5     A     b     A     b         TRUE         TRUE
6     A     b     A  <NA>         TRUE         TRUE
7     A  <NA>     A     a         TRUE         TRUE
8     A  <NA>     A     b         TRUE         TRUE
9     A  <NA>     A  <NA>         TRUE         TRUE
Run Code Online (Sandbox Code Playgroud)

此代码也无法给出所需的输出:

good_perms2 <- perms %>% 
    dplyr::mutate(LET_mismatch = isFALSE(LET_1 == LET_2)) %>% 
    dplyr::mutate(let_mismatch = isFALSE(let_1 == let_2)) 

> good_perms2
  LET_1 let_1 LET_2 let_2 LET_mismatch let_mismatch
1     A     a     A     a        FALSE        FALSE
2     A     a     A     b        FALSE        FALSE
3     A     a     A  <NA>        FALSE        FALSE
4     A     b     A     a        FALSE        FALSE
5     A     b     A     b        FALSE        FALSE
6     A     b     A  <NA>        FALSE        FALSE
7     A  <NA>     A     a        FALSE        FALSE
8     A  <NA>     A     b        FALSE        FALSE
9     A  <NA>     A  <NA>        FALSE        FALSE
Run Code Online (Sandbox Code Playgroud)

如果我使用下面的代码,当定义值时我会得到预期的结果,但我得到的NA不是期望的结果:

  • FALSE当其中一个值是NA
  • TRUE当两个值都是NA
good_perms2 <- perms %>% 
    dplyr::mutate(LET_mismatch = (LET_1 != LET_2)) %>% 
    dplyr::mutate(let_mismatch = (let_1 != let_2)) 

> good_perms2
  LET_1 let_1 LET_2 let_2 LET_mismatch let_mismatch
1     A     a     A     a        FALSE        FALSE
2     A     a     A     b        FALSE         TRUE
3     A     a     A  <NA>        FALSE           NA
4     A     b     A     a        FALSE         TRUE
5     A     b     A     b        FALSE        FALSE
6     A     b     A  <NA>        FALSE           NA
7     A  <NA>     A     a        FALSE           NA
8     A  <NA>     A     b        FALSE           NA
9     A  <NA>     A  <NA>        FALSE           NA
Run Code Online (Sandbox Code Playgroud)

我意识到这里可能存在三个问题,但第一个问题是我最困惑的:

  1. 为什么和都dplyr::mutate计算!isTRUE为?同样对于.TRUE!isTRUE("a" == "a")!isTRUE("a" == "b")isFALSE
  2. 我如何(最好是在一个函数中)识别NA == "a"asFALSENA == NAas TRUE

s的问题NA可能需要单独解决,我现在主要关心的是为什么 s!isTRUE内部的行为不符合预期dplyr::mutate。谢谢!

PS这篇文章涉及这个问题,但通过不同的方式解决了。

www*_*www 1

也许替换NA为字符“NA”,运行代码,然后将字符“NA”替换回NA

library(dplyr)

good_perms2 <- perms %>% 
  mutate_all(list(~replace(., is.na(.), "NA"))) %>%
  mutate(LET_mismatch = (LET_1 != LET_2)) %>% 
  mutate(let_mismatch = (let_1 != let_2)) %>%
  mutate_all(list(~replace(., . %in% "NA", NA_character_)))
good_perms2 
#   LET_1 let_1 LET_2 let_2 LET_mismatch let_mismatch
# 1     A     a     A     a        FALSE        FALSE
# 2     A     a     A     b        FALSE         TRUE
# 3     A     a     A  <NA>        FALSE         TRUE
# 4     A     b     A     a        FALSE         TRUE
# 5     A     b     A     b        FALSE        FALSE
# 6     A     b     A  <NA>        FALSE         TRUE
# 7     A  <NA>     A     a        FALSE         TRUE
# 8     A  <NA>     A     b        FALSE         TRUE
# 9     A  <NA>     A  <NA>        FALSE        FALSE
Run Code Online (Sandbox Code Playgroud)