一个可重现的例子:
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]
快速介绍逻辑运算符:这里和这里。
更新:
我不确定您为什么要摆脱NAs ,因为上述所有建议都适用于它们。首先,保持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" )