使用grepl筛选非缺失不匹配项时,is.na()的正确放置位置
问题说明
我想要筛选出var2中非缺失且不包含指定表达式的条目,并获取对应的var1值。默认情况下grepl会返回缺失条目对应的NA,这是我需要避免的。我写了两种实现方式,其中一种结果错误,想了解错误的原因。
代码与输出
df <- data.frame( var1 = 1:150, var2 = c(rep(NA, 100), rep("ABC", 45), rep("CBA", 5)) ) exp <- "BC" ## 正确结果 df$var1[!grepl(exp, df$var2, fixed=T) & !is.na(df$var2)] # [1] 146 147 148 149 150 ## 错误结果 df$var1[!grepl(exp, df$var2[!is.na(df$var2)], fixed=T)] # [1] 46 47 48 49 50 96 97 98 99 100 146 147 148 149 150 # 查看错误结果对应的var2值 print(df[c(46, 47, 48, 49, 50, 96, 97, 98, 99, 100, 146, 147, 148, 149, 150), "var2"]) # [1] NA NA NA NA NA NA NA NA NA NA "CBA" "CBA" "CBA" "CBA" "CBA"
错误原因分析
第二种写法的问题出在索引长度不匹配:
df$var2[!is.na(df$var2)]提取了var2中非缺失的子集,长度为50(45个"ABC"+5个"CBA")。grepl(exp, ...)返回长度为50的逻辑向量:45个TRUE("ABC"包含"BC")和5个FALSE("CBA"不包含"BC"),取反后变成45个FALSE和5个TRUE。- 当用这个长度为50的逻辑向量去索引长度为150的
df$var1时,R会触发循环补齐机制——把50个元素的向量重复3次,凑成150个元素。 - 重复后的逻辑向量中,第46-50位、96-100位、146-150位是
TRUE,但前两组位置对应的var2其实是NA,这就错误选中了原本不符合条件的行。
正确写法的逻辑是对整个var2列做判断:!grepl(exp, df$var2, fixed=T) & !is.na(df$var2)生成长度为150的逻辑向量,只有var2非缺失且不包含目标表达式的位置才是TRUE,因此能精准筛选出正确的var1值。
内容的提问来源于stack exchange,提问作者Joschi Nin
相关产品推荐
相关产品推荐

