如何使用dplyr过滤数据而不丢失NA行

29

如何在R中对数据进行子集操作而不会丢失NA行?

上面的帖子使用逻辑索引进行子集操作。 是否有一种方法可以在dplyr中完成它?

此外,dplyr什么时候会自动删除NAs?根据我的经验,当我过滤掉特定字符串时,它会删除NA:

b = a %>% filter(col != "str")

我原本以为这个方法不会排除NA值,但事实却是这样。但是,当我使用其他过滤格式时,它不会自动排除NA,例如:

b = a %>% filter(!grepl("str", col))

我想了解filter的这个功能。 我会感激任何帮助。 谢谢!


这里是软件包的作者评论:https://github.com/tidyverse/dplyr/issues/3196#issuecomment-342599352 - Ruam Pimentel
3个回答

39

dplyr::filter的文档中写道:“与基本子集不同,条件计算结果为NA的行将被删除。”

NA != "str" 计算结果为 NA ,因此被 filter 删除。

!grepl("str", NA) 返回 TRUE ,因此保留。

如果您希望 filter 保留 NA,可以使用 filter(is.na(col)|col!="str")


2
这个解决方案不可行,因为如果col != "str"返回FALSE但is.na(col)返回TRUE,它将被保留。所以过滤器失败了。实际上我在一个过滤器中使用了两个过滤器示例。所以它变成了b = a %>% filter(col != "str1", !grepl("str2", col))。这就是我做的,但它也过滤掉了NA...这就是问题所在。 - Brent Carbonera
dplyr::filter的行为类似于SQL中的 SELECT ... WHERE cond,因为SELECT子句丢弃了NULL条件。 - qwr

18

如果你希望保留由过滤条件创建的NA值,你可以使用tidyr中的replace_na条件的NA值简单地替换为TRUE值。

a <- data.frame(col = c("hello", NA, "str"))
a %>% filter((col != "str") %>% replace_na(TRUE))

这是唯一一个真正为我解决问题的解决方案!非常优雅!谢谢!! - James Cutler

3

我刚遇到了这个问题。很容易被忽略,而且我必须说我觉得这种行为有些不直观。基于qwr的答案,从现在起,我所有的项目都会采用这种做法:

filter_na <- function(tbl, expr){
   tbl %>% filter({{expr}} %>% replace_na(T))
}

行为与SQL WHERE匹配,因为它在SQL的三值逻辑中删除了UNKNOWN。 - qwr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接