使用subset或dplyr :: filter时,过滤R中的行会意外删除NAs

时间:2016-03-31 20:16:42

标签: r filter dplyr subset

我有一个数据集df,我想删除变量y没有值a的所有行。变量y还包含一些NAs

df <- data.frame(x=1:3, y=c('a', NA, 'c'))

我可以使用R的索引语法实现这一点:

df[df$y!='a',]

  x    y
  2 <NA>
  3    c

请注意,这会返回NA和值c - 这就是我想要的。

但是,当我使用subsetdplyr::filter尝试相同的操作时,NA会被删除:

subset(df, y!='a')

  x    y
  3    c

dplyr::filter(df, y!='a')
  x    y
  3    c

为什么subsetdplyr::filter会像这样工作?这对我来说似乎不合逻辑 - NAa不同,所以为什么在我指定我想要除变量NA等于的所有行之外删除y a

除了明确要求NAs返回之外,还有一些方法可以改变这些功能的行为,即

subset(df, y!='a' | is.na(y))

由于

2 个答案:

答案 0 :(得分:8)

“预期”行为的示例实际上并不会返回您在问题中显示的内容。我明白了:

> df[df$y != 'a',]
    x    y
NA NA <NA>
3   3    c

这可能比<{1}}和subset返回的更多错误。请记住,在R中,dplyr::filter的意思是“未知”,因此NA会返回,

df$y != 'a'

所以R被告知你肯定不想要第一行,你确实想要最后一行,但是你是否想要第二行字面意思是“未知”。因此,它包含一行> df$y != 'a' [1] FALSE NA TRUE s。

许多人不喜欢这种行为,但它就是这样。

NAsubset提供了一个不同的默认选择,即只删除dplyr::filter行,这可能是准确的。

但实际上,这里的教训是,如果您的数据有NA s,那就意味着您需要通过使用NA之类的条件,或者如上所述,在所有点进行防御性编码在另一个答案中使用基于is.na(df$y) | df$y != 'a'的{​​{1}}。

答案 1 :(得分:7)

一种解决方法是使用%in%

subset(df, !y %in% "a")
dplyr::filter(df, !y %in% "a")