如何在不丢失R中的NA值的情况下有条件地从数据帧中删除观测值?

Ely*_*Ely 5 r subset missing-data na

在数据框中有一个名为的变量YOB.如您所见,有333个NA值.

> summary(train$YOB)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
   1880    1970    1983    1980    1993    2039     333 
Run Code Online (Sandbox Code Playgroud)

我发现了一些异常值并希望摆脱它们.任何低于1900且大于2003的东西都应被删除.我尝试通过索引来做到这一点.

train = train[which(train$YOB >= 1900 & train$YOB <= 2003),]
Run Code Online (Sandbox Code Playgroud)

不幸的是,其YOB变量的观察NA也被删除了.

> summary(train$YOB)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1900    1970    1983    1980    1993    2003 
Run Code Online (Sandbox Code Playgroud)

另外,在使用subset命令时我遇到了同样的问题.

> train = subset(train, YOB >= 1900 & YOB <= 2003)
> summary(train$YOB)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1900    1970    1983    1980    1993    2003 
Run Code Online (Sandbox Code Playgroud)

我也试图在两次尝试中使用这个条件,但没有成功,例如

> train = train[which(!is.na(train$YOB) & train$YOB >= 1900 & train$YOB <= 2003),]
> summary(train$YOB)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1900    1970    1983    1980    1993    2003 
Run Code Online (Sandbox Code Playgroud)

我想保留已观测NA的YOB变量,只删除那些数字.这个想法是第二步,以弥补缺失的价值观.

akr*_*run 3

将which给出数字索引并跳过所有那些 NA 行。为了避免这种情况,请使用逻辑索引而不用which. 这样,索引将为 NA,并且即使存在其他非 NA 值,该行也将保持为 NA。

res1 <- train[train$YOB >= 1900 & train$YOB <= 2003,]
res1[is.na(res1$YOB),]
#   YOB col2
#NA  NA   NA
Run Code Online (Sandbox Code Playgroud)

正确的方法是有另一个条件is.na

res2 <- train[is.na(train$YOB)| (train$YOB >= 1900 & train$YOB <= 2003),]
res2[is.na(res2$YOB),]
#   YOB      col2
#42  NA 0.2258094
Run Code Online (Sandbox Code Playgroud)

使用一个简单的例子

set.seed(25)
d1 <- data.frame(v1 = c(NA, 1, 5), v2 = rnorm(3))
d1$v1 >1
#[1]    NA FALSE  TRUE
Run Code Online (Sandbox Code Playgroud)

在这里,NA该值保持不变。如果我们使用which

which(d1$v1 >1)
#[1] 3
Run Code Online (Sandbox Code Playgroud)

我们只得到 TRUE 值的索引。根据OP,NA和满足逻辑条件的行都应该返回。在这种情况下,

d1[is.na(d1$v1)|d1$v1 > 1,]
# v1         v2
#1 NA -0.2118336
#3  5 -1.1533076
Run Code Online (Sandbox Code Playgroud)

数据

set.seed(29)
train <- data.frame(YOB = sample(c(NA, 1850:2015), 100, replace=TRUE), 
           col2 = rnorm(100))
Run Code Online (Sandbox Code Playgroud)