R,dplyr:如何根据其他列中的 NA 值将一列中的值更改为 NA(使用 OR 运算符)

ste*_*--g 5 r na dplyr tidyverse

这个问题很难用标题行来表达,但它与通常的“如何根据另一列中的值更改一列中的值”不同。有两个问题我在其他地方没有看到处理过:1)我正在处理 NA,而不是值,2)我正在处理涉及多个列之间 OR 关系的条件,即 if is V01NA V02is NA ,然后使foo该行的 var(已存在但没有 NA)为 NA。

这是一个小问题来说明:

tbl <- tibble(
  V01 = 10:15,
  V02 = 1:6,
  V03 = V02 * 2,
  foo = V03 * 2
)
# sprinkle around some NAs
tbl[1,2] = NA
tbl[4,1] = NA
tbl[4,2] = NA
tbl[6,1:3] = NA
Run Code Online (Sandbox Code Playgroud)

产生这个表:

# A tibble: 6 x 4
    V01   V02   V03   foo
  <int> <int> <dbl> <dbl>
1    10    NA     2     4
2    11     2     4     8
3    12     3     6    12
4    NA    NA     8    16
5    14     5    10    20
6    NA    NA    NA    24
Run Code Online (Sandbox Code Playgroud)

最终我想为中的每一行生成这种逻辑tbl

if (V01 == NA | V02 == NA | V03 == NA) {foo = NA}
Run Code Online (Sandbox Code Playgroud)

我首先尝试根据一列mutate更改foo为 NA,如下所示:

tbl <- tbl %>% 
  mutate(
  foo = case_when(V01 == NA ~ NA)
  )
Run Code Online (Sandbox Code Playgroud)

但即使在这个简单的情况下,mutate 也将 的每个值更改foo为 NA:

# A tibble: 6 x 4
    V01   V02   V03 foo  
  <int> <int> <dbl> <lgl>
1    10    NA     2 NA   
2    11     2     4 NA   
3    12     3     6 NA   
4    NA    NA     8 NA   
5    14     5    10 NA   
6    NA    NA    NA NA   
Run Code Online (Sandbox Code Playgroud)

我想也许我需要rowwise在那里,但这并没有改变结果。

然后我想也许是因为 NA 很奇怪,所以让我们尝试一些更简单的方法:如果是 NA则更改为foo-1 :V01

tbl <- tbl %>% 
  mutate(
  foo = case_when(V01 == NA ~ -1)
  )
Run Code Online (Sandbox Code Playgroud)

但这产生了相同的结果,所有 的值都foo更改为 NA(并且第 4 行中的值foo也没有更改为 -1)。

然后我决定做一些更简单的事情。将 NA 排除在外。如果V01为 10(仅在第一行中),则foo将该行中的值更改为 -1。所以:

tbl <- tbl %>% 
  mutate(
  foo = case_when(V01 == 10 ~ -1)
  )
Run Code Online (Sandbox Code Playgroud)

这就产生了这个:

# A tibble: 6 x 4
    V01   V02   V03   foo
  <int> <int> <dbl> <dbl>
1    10    NA     2    -1
2    11     2     4    NA
3    12     3     6    NA
4    NA    NA     8    NA
5    14     5    10    NA
6    NA    NA    NA    NA
Run Code Online (Sandbox Code Playgroud)

那么为什么要mutate更改不满足语句中指定条件的行中的值呢mutate

请注意,我什至还没有达到 OR 条件。就其价值而言,这就是我想要得到的结果:

# A tibble: 6 x 4
    V01   V02   V03   foo
  <int> <int> <dbl> <dbl>
1    10    NA     2    NA
2    11     2     4     8
3    12     3     6    12
4    NA    NA     8    NA
5    14     5    10    20
6    NA    NA    NA    NA
Run Code Online (Sandbox Code Playgroud)

我无法使用 dplyrna_if函数,因为它只需要一个值来替换为 NA,而不是一个条件。

任何指导将不胜感激。谢谢!

Ron*_*hah 1

这里有几个选项 -

  1. 使用rowSums-
library(dplyr)
tbl %>%
  mutate(foo = replace(foo, rowSums(is.na(select(., starts_with('V')))) > 0, NA))

#    V01   V02   V03   foo
#  <int> <int> <dbl> <dbl>
#1    10    NA     2    NA
#2    11     2     4     8
#3    12     3     6    12
#4    NA    NA     8    NA
#5    14     5    10    20
#6    NA    NA    NA    NA
Run Code Online (Sandbox Code Playgroud)
  1. 使用rowwise-
tbl %>%
  rowwise() %>%
  mutate(foo = if(any(is.na(c_across(starts_with('V'))))) NA else foo)
Run Code Online (Sandbox Code Playgroud)

如果任何以 开头的列中有值,则这两个值都会替换foo为。NANAV


就这段代码而言

tbl <- tbl %>% 
  mutate(foo = case_when(V01 == 10 ~ -1))
Run Code Online (Sandbox Code Playgroud)

case_whenNA如果不满足条件则默认返回。要获得相同的价值,你可以这样做

tbl %>% 
  mutate(foo = case_when(V01 == 10 ~ -1, 
                        TRUE ~ foo))
Run Code Online (Sandbox Code Playgroud)