将相同条件应用于case_when函数中的多个变量的替代方法

时间:2019-05-20 01:09:10

标签: r

我正在尝试为case_when函数中的多个条件找到一个更有效或更优雅的解决方案。

我正在基于跨数据帧特定列的多个条件创建一个虚拟列。在许多情况下,许多列都使用相同的is.na()。我得到了正确的结果,但是我尝试使用applyreduceanyNa的其他方法都没有成功。

让我们说这个数据框看起来像我正在处理的数据:

set.seed(12)
dframe <- data.frame(
  x1 = sample(letters[1:2], 10, replace = TRUE),
  x2 = sample(0:1, 10, replace = TRUE),
  x3 = sample(0:2, 10, replace = TRUE),
  x4 = sample(0:2, 10, replace = TRUE),
  x5 = sample(0:2, 10, replace = TRUE),
  x6 = sample(0:2, 10, replace = TRUE)
) %>% 
  mutate_if(is.numeric, list(~na_if(., 2)))

它看起来像这样:

   x1 x2 x3 x4 x5 x6
1   b  1 NA  0  0  0
2   b  0  0  0 NA NA
3   b  1  0  0  0  1
4   a  0 NA  1 NA  0
5   a  1  1 NA NA NA
6   b  0 NA  1  1  1
7   a  1  1 NA NA  0
8   a  1  0  1 NA  0
9   b  1 NA NA  0  0
10  b  1  1  0 NA NA

然后,我根据以下条件创建列x7

dframe %>% 
  mutate(
    x7 = case_when(
      x2 == 1 & 
      (!is.na(x3) | !is.na(x4) | !is.na(x5)) & 
      !is.na(x6) ~ 1,
      x2 == 1 ~ 0,
      TRUE ~ NA_real_
    )
  )

导致:

   x1 x2 x3 x4 x5 x6 x7
1   b  1 NA  0  0  0  1
2   b  0  0  0 NA NA NA
3   b  1  0  0  0  1  1
4   a  0 NA  1 NA  0 NA
5   a  1  1 NA NA NA  0
6   b  0 NA  1  1  1 NA
7   a  1  1 NA NA  0  1
8   a  1  0  1 NA  0  1
9   b  1 NA NA  0  0  1
10  b  1  1  0 NA NA  0

但是,我想找到一种替代方法来编写(!is.na(x3) | !is.na(x4) | !is.na(x5)),因为在我的真实脚本中,我必须为此输入11列。

我尝试使用complete.cases(x3, x4, x5),但是它不符合我在代码中使用的逻辑。

使用anyNA(x3, x4, x5)会抛出Error in anyNA(x3, x4, x5) : anyNA takes 1 or 2 arguments

也尝试了similar problem的答案,但是由于我没有将其用于过滤,因此无法解决问题。

也许我想得太多了,但是我要寻找的是无需使用(!is.na(x3) | !is.na(x4) | !is.na(x5))的东西。

1 个答案:

答案 0 :(得分:1)

我们可以使用rowSums并按名称指定列

library(dplyr)

dframe %>% 
  mutate(x7 = case_when(
               x2 == 1 & 
               rowSums(!is.na(.[c("x3","x4","x5")])) > 0 &
               !is.na(x6) ~ 1,
               x2 == 1 ~ 0,
               TRUE ~ NA_real_
              )
          )

或按位置

rowSums(!is.na(.[3:5])) > 0

我们也可以使用反向逻辑来做到这一点。

rowSums(is.na(.[c("x3","x4","x5")])) != 3

rowSums(is.na(.[3:5])) != 3

我们在这里使用3,因为在给定的示例中有3列要检查(x3x4x5),您可以根据实际的列数来更改数目(11)。