在R中如何对数据进行子集提取而不丢失NA行?

9

我正在使用R查看一些数据。其中一个名为“Height”的列包含了几行NA。

我希望对数据框进行子集化,以便排除所有高度值大于某个特定值的数据行,不参与我的分析。

df2 <- subset ( df1 , Height < 40 )

然而,每当我这样做时,R自动删除包含Height的NA值的所有行。我不想要这个。我已经尝试过在na.rm参数中包含参数。
f1 <- function ( x , na.rm = FALSE ) {
df2 <- subset ( x , Height < 40 )
}
f1 ( df1 , na.rm = FALSE )

但这似乎没有任何作用;带有NA的行仍然会从我的数据框中消失。有没有一种方法可以这样子分割我的数据,而不会丢失NA行呢?


我们也可以使用 subset(df1, Height < 40 | is.na(Height)) - Zach
为了完整起见,dplyr 包中类似的选项是 filter(df1, Height < 40 | is.na(Height)) - Simon Jackson
3个回答

18

如果我们决定使用subset函数,那么需要注意:

For ordinary vectors, the result is simply ‘x[subset & !is.na(subset)]’.

因此,只有非 NA 值将被保留。

如果您希望保留 NA 情况,请使用逻辑或条件告诉 R 不要删除 NA 情况:

subset(df1, Height < 40 | is.na(Height))
# or `df1[df1$Height < 40 | is.na(df1$Height), ]`

不要直接使用(很快会解释):

df2 <- df1[df1$Height < 40, ]

例子

df1 <- data.frame(Height = c(NA, 2, 4, NA, 50, 60), y = 1:6)

subset(df1, Height < 40 | is.na(Height))

#  Height y
#1     NA 1
#2      2 2
#3      4 3
#4     NA 4

df1[df1$Height < 40, ]

#  Height  y
#1     NA NA
#2      2  2
#3      4  3
#4     NA NA

后者失败的原因是使用 NA 进行索引会得到 NA。考虑这个简单向量的例子:

x <- 1:4
ind <- c(NA, TRUE, NA, FALSE)
x[ind]
# [1] NA  2 NA

我们需要用TRUE替换那些NA。最直接的方法是添加另一个“or”条件is.na(ind)

x[ind | is.na(ind)]
# [1] 1 2 3

这正是在您的情况下会发生的事情。如果您的Height包含NA,那么逻辑运算Height <40最终会变成TRUE/FALSE/NA的混合,因此我们需要像上面那样用TRUE替换NA


1

对于基于字符/因子变量的子集,您可以使用%in%来保留NA。指定您希望排除的数据。

# Create Dataset
library(data.table)
df=data.table(V1=c('Surface','Bottom',NA),V2=1:3)
df
#         V1 V2
# 1: Surface  1
# 2:  Bottom  2
# 3:    <NA>  3

# Keep all but 'Bottom'
df[!V1 %in% c('Bottom')]
#         V1 V2
# 1: Surface  1
# 2:    <NA>  3

这是因为%in%从不返回NA(详见?match)。

1

你也可以这样做:

df2 <- df1[(df1$Height < 40 | is.na(df1$Height)),]

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