在使用子集或 dplyr::filter 时过滤 R 中的行意外删除 NA
Filtering rows in R unexpectedly removes NAs when using subset or dplyr::filter
我有一个数据集 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
请注意 returns NA
和值 c
- 这正是我想要的。
但是,当我使用 subset
或 dplyr::filter
尝试相同的操作时,NA
被删除:
subset(df, y!='a')
x y
3 c
dplyr::filter(df, y!='a')
x y
3 c
为什么 subset
和 dplyr::filter
是这样工作的?这对我来说似乎不合逻辑 - NA
与 a
不同,所以当我指定我想要除变量 y
等于的那些行之外的所有行时,为什么要删除 NA
a
?
有什么方法可以改变这些函数的行为,而不是明确要求 NAs
返回,即
subset(df, y!='a' | is.na(y))
谢谢
一种解决方法是使用 %in%
:
subset(df, !y %in% "a")
dplyr::filter(df, !y %in% "a")
您的“预期”行为示例实际上 return 您在问题中显示的内容。我得到:
> df[df$y != 'a',]
x y
NA NA <NA>
3 3 c
可以说,这比 subset
和 dplyr::filter
return 的错误 多 。请记住,在 R 中,NA
的真正意思是“未知”,因此 df$y != 'a'
returns,
> df$y != 'a'
[1] FALSE NA TRUE
所以 R 被告知您绝对不想要第一行,您确实想要最后一行,但是您是否想要第二行实际上是“未知”的。结果,它包括一行所有 NA
s.
很多人不喜欢这种行为,但事实就是如此。
subset
和 dplyr::filter
做出不同的默认选择,即简单地删除 NA
行,这可以说是准确的。
但实际上,这里的教训是,如果你的数据有 NA
s,那只意味着你需要在所有点上围绕它进行防御性编码,或者通过使用像 is.na(df$y) | df$y != 'a'
这样的条件,或者如另一个答案中所述,使用基于 match
.
的 %in%
来自 base::Extract
:
When extracting, a numerical, logical or character NA
index picks an unknown element and so returns NA
来自 ?base::subset
:
missing values are taken as false [...] For ordinary vectors, the result is simply x[subset & !is.na(subset)]
来自?dplyr::filter
Unlike base subsetting with [
, rows where the condition evaluates to NA
are dropped
我有一个数据集 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
请注意 returns NA
和值 c
- 这正是我想要的。
但是,当我使用 subset
或 dplyr::filter
尝试相同的操作时,NA
被删除:
subset(df, y!='a')
x y
3 c
dplyr::filter(df, y!='a')
x y
3 c
为什么 subset
和 dplyr::filter
是这样工作的?这对我来说似乎不合逻辑 - NA
与 a
不同,所以当我指定我想要除变量 y
等于的那些行之外的所有行时,为什么要删除 NA
a
?
有什么方法可以改变这些函数的行为,而不是明确要求 NAs
返回,即
subset(df, y!='a' | is.na(y))
谢谢
一种解决方法是使用 %in%
:
subset(df, !y %in% "a")
dplyr::filter(df, !y %in% "a")
您的“预期”行为示例实际上 return 您在问题中显示的内容。我得到:
> df[df$y != 'a',]
x y
NA NA <NA>
3 3 c
可以说,这比 subset
和 dplyr::filter
return 的错误 多 。请记住,在 R 中,NA
的真正意思是“未知”,因此 df$y != 'a'
returns,
> df$y != 'a'
[1] FALSE NA TRUE
所以 R 被告知您绝对不想要第一行,您确实想要最后一行,但是您是否想要第二行实际上是“未知”的。结果,它包括一行所有 NA
s.
很多人不喜欢这种行为,但事实就是如此。
subset
和 dplyr::filter
做出不同的默认选择,即简单地删除 NA
行,这可以说是准确的。
但实际上,这里的教训是,如果你的数据有 NA
s,那只意味着你需要在所有点上围绕它进行防御性编码,或者通过使用像 is.na(df$y) | df$y != 'a'
这样的条件,或者如另一个答案中所述,使用基于 match
.
%in%
来自 base::Extract
:
When extracting, a numerical, logical or character
NA
index picks an unknown element and so returnsNA
来自 ?base::subset
:
missing values are taken as false [...] For ordinary vectors, the result is simply
x[subset & !is.na(subset)]
来自?dplyr::filter
Unlike base subsetting with
[
, rows where the condition evaluates toNA
are dropped