一个可重现的例子:
vals1 <- c(NA, "pos", "neg", "nr")
set.seed(1)
df1 <- data.frame(
id = seq(1:10),
a09 = sample(vals1,10,replace=TRUE),
a10 = sample(vals1,10,replace=TRUE),
a11 = sample(vals1,10,replace=TRUE),
b10 = sample(vals1,10,replace=TRUE),
b11 = sample(vals1,10,replace=TRUE)
)
### modify to give at least one case meeting each of your criteria
df1[10,c(5,6)] <- NA # 2x NAs for b's
df1[1,c(2,3,4)] <- NA # 3x NAs for a's
df1[2,c(2,4,5,6)] <- NA # all NAs
给予:
id a09 a10 a11 b10 b11
1 1 <NA> <NA> <NA> pos nr
2 2 <NA> <NA> <NA> <NA> <NA>
3 3 neg neg neg pos nr
4 4 nr pos <NA> <NA> neg
5 5 <NA> nr pos nr neg
6 6 nr pos pos neg nr
7 7 nr neg <NA> nr <NA>
8 8 neg nr pos <NA> pos
9 9 neg pos nr neg neg
10 10 <NA> nr pos <NA> <NA>
现在我们链接多个逻辑运算符来获取有问题的 id。这不像上面的@Carls 建议那么优雅,但乍一看可能更直观......请注意分组括号,即a and (b or c)
:
### test a not b, id=10
df1$id[ is.na(df1$b10) & is.na(df1$b11) &
( !is.na(df1$a09) | !is.na(df1$a10) | !is.na(df1$a11) ) ]
### test b not a, id=1
df1$id[ is.na(df1$a09) & is.na(df1$a10) & is.na(df1$a11) &
& ( !is.na(df1$b10) | !is.na(df1$b11) ) ]
最后一个示例使用了在传递给期望数字的方法时R
将转换TRUE
为的事实。1
在这种情况下,我们要检查该行中的所有 5 个值是否NA
然后使用否定(表示 NOT)获取其他行。!
### a and b, id= all except no. 2
df1$id[!rowSums(is.na(df1[ ,2:6]))==5]
快速介绍逻辑运算符:这里和这里。
更新:
我不确定您为什么要摆脱NA
s ,因为上述所有建议都适用于它们。首先,保持NA
并遵循您的表达方式:
TestA <-ifelse( !is.na(df1$a09) | !is.na(df1$a10) | !is.na(df1$a11), "TESTa","NOtesta")
TestB <-ifelse( !is.na(df1$b10) | !is.na(df1$b11), "TESTb", "NOtestb")
TestAonly <- (TestA=="TESTa" & TestB=="NOtestb")
TestAandTestB <- (TestA=="TESTa" & TestB=="TESTb")
请注意,您需要在 eg 周围加上引号Testa
,否则R
会尝试将其作为变量而不是字符串文字来查找。您也可以考虑为变量采用更简单的命名约定/样式,例如dot.seperator。
结果将是一个与 长度相同的逻辑向量nrow(df1)
。
如果您坚持使用1
或0
使用以下内容:
TestB <-ifelse( df1$b10==1 | df1$b11==1, "TESTb", "NOtestb" )