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

jay*_*jay 3 r subset filter dplyr

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

df <- data.frame(x=1:3, y=c('a', NA, 'c'))
Run Code Online (Sandbox Code Playgroud)

我可以使用R的索引语法实现这一点,如下所示:

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

  x    y
  2 <NA>
  3    c
Run Code Online (Sandbox Code Playgroud)

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

然而,当我使用同样的尝试subset或者dplyr::filter,将NA被剥离出来:

subset(df, y!='a')

  x    y
  3    c

dplyr::filter(df, y!='a')
  x    y
  3    c
Run Code Online (Sandbox Code Playgroud)

为什么subsetdplyr::filter这样的工作吗?这对我来说似乎不合逻辑 - 这NA是不一样的a,所以为什么要删除NA当我指定我想要除变量y等于的那些行之外的所有行a

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

subset(df, y!='a' | is.na(y))
Run Code Online (Sandbox Code Playgroud)

谢谢

jor*_*ran 8

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

> df[df$y != 'a',]
    x    y
NA NA <NA>
3   3    c
Run Code Online (Sandbox Code Playgroud)

这可能比什么和回归更加错误.请记住,在R中,真的意思是"未知",所以返回,subsetdplyr::filterNAdf$y != 'a'

> df$y != 'a'
[1] FALSE    NA  TRUE
Run Code Online (Sandbox Code Playgroud)

所以R被告知你肯定不想要第一行,你确实想要最后一行,但是你是否想要第二行字面意思是"未知".结果,它包括一行所有NAs.

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

subsetdplyr::filter做出一个不同的默认选择,即简单地删除NA行,这可能是准确的.

不过说真的,这里的教训是,如果你的数据有NAS,那只是意味着你需要在所有的点,或者通过使用条件,喜欢周围的防御性代码is.na(df$y) | df$y != 'a',或通过使用其他答复中提到%in%这是基于match.

  • 这些所谓的人们认为`df $ y!='a'`应该返回什么?NA是不可比较的,所以它不能返回TRUE或FALSE,并且`==`是矢量化的,所以它不能返回长度为2的东西 (2认同)

tfc*_*tfc 7

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

subset(df, !y %in% "a")
dplyr::filter(df, !y %in% "a")
Run Code Online (Sandbox Code Playgroud)