我正在尝试为case_when
函数中的多个条件找到一个更有效或更优雅的解决方案。
我正在基于跨数据帧特定列的多个条件创建一个虚拟列。在许多情况下,许多列都使用相同的is.na()
。我得到了正确的结果,但是我尝试使用apply
,reduce
和anyNa
的其他方法都没有成功。
让我们说这个数据框看起来像我正在处理的数据:
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))
的东西。
答案 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列要检查(x3
,x4
和x5
),您可以根据实际的列数来更改数目(11)。