3

我有一个代码正在做类似的事情

d <- load a data.frame, possible an empty one...
d <- na.omit(d)
if (NROW(d)>0) {
 do something...
}

这似乎是错误的,因为应用na.omit到空数据框会为其添加一行:

data.frame()  
data frame with 0 columns and 0 rows

na.omit(data.frame())  
data frame with 0 columns and 1 rows

为什么 na.omit 对我这样做?

4

2 回答 2

4

这是因为na.omit有一个逻辑向量omit(在其代码中)被设置FALSE保留TRUE那些行和删除那些行。

但是,omit在检查您的输入 data.frame 以了解要删除哪些行并更新omit. 由于您的输入是一个空的 data.frame,因此没有更新的值并omit保留之前设置的 FALSE。然后,na.omit调用:

object[!omit, , drop=FALSE]

在您的情况下是:

data.frame()[TRUE, , drop=FALSE]

这使:

# data frame with 0 columns and 1 rows

这是na.omit.data.frame(可以通过do获得getS3method("na.omit", "data.frame"))的代码。未为您的空 data.frame 运行的部分被注释掉。

n <- length(object)
omit <- FALSE
vars <- seq_len(n) # equals integer(0) in your case
for (j in vars) { # the loop is not run at all
#     x <- object[[j]]
#     if (!is.atomic(x)) 
#         next
#     x <- is.na(x)
#     d <- dim(x)
#     if (is.null(d) || length(d) != 2L) 
#         omit <- omit | x
#     else for (ii in 1L:d[2L]) omit <- omit | x[, ii]
# }
xx <- object[!omit, , drop = FALSE]
# if (any(omit > 0L)) { # this is also not run
#     temp <- setNames(seq(omit)[omit], attr(object, "row.names")[omit])
#     attr(temp, "class") <- "omit"
#     attr(xx, "na.action") <- temp
# }
xx

解决方案:

你可以complete.cases改用。

DF <- data.frame()
DF[complete.cases(DF), ]
# data frame with 0 columns and 0 rows

DF <- data.frame(x=1:2, y=c(2,NA))
DF[complete.cases(DF), ]
#   x y
# 1 1 2    
于 2013-05-14T09:57:30.377 回答
1

问题不在于(必然) with na.omit,而在于索引data.frame没有行的 a 。例如:

> DF <- data.frame()
> DF[TRUE, ]
data frame with 0 columns and 1 rows
> DF[1, ]
data frame with 0 columns and 1 rows
> DF
data frame with 0 columns and 0 rows

您不能真正索引 data.frame 并取回 0 行 data.frame。

一种解决方法是使用条件逻辑:

if (!nrow(DF))
  do nothing
else 
  na.omit(DF) ... 

更好的解决方法是使用@Arun 的建议

于 2013-05-14T09:57:17.943 回答