让我们考虑以下变量:
y <- factor(5:1, levels = 1:5, labels <- c(1:4, NA))
选择没有标签NA的所有值的最佳方法是什么?
> !is.na(y)
[1] FALSE FALSE FALSE FALSE FALSE
可以使用因子值,但是记录NA的值很麻烦:
> as.integer(y)
[1] 1 2 3 4 5
> as.integer(y) == which(is.na(levels(y)))
[1] FALSE FALSE FALSE FALSE TRUE
转换为字符似乎可行,但这在计算上似乎不是最佳选择:
> as.character(y)
[1] "1" "2" "3" "4" NA
> is.na(as.character(y))
[1] FALSE FALSE FALSE FALSE TRUE
还有其他(有效的)想法很容易处理吗?
注意:这个问题专门涉及将NA作为要素水平。一般而言,这与选择值无关。事实证明,最通用的方法可以按预期方式进行处理-请参阅下面的注释。
注释2:由于y[!y %in% NA]
的工作方式,似乎可以使用%in%
。从文档中:“因素,原始向量和列表将转换为字符向量。”即%in%
的使用实际上等同于上述基于as.character
的方法。不过,应避免这种转换-这是此问题带来的问题。
顺便说一句,这是上述方法的次要标准:
library(microbenchmark)
y <- factor(rep(5:1, 1000000), levels = 1:5, labels <- c("foo", "foo bar", "foobar bar", "foo foobar", NA))
microbenchmark(
as.integer(y) == which(is.na(levels(y))),
is.na(as.character(y)),
y %in% NA,
is.na(levels(y)[y]),
## times = 1e5,
times = 100,
check = function (values) {
all(sapply(values[-1], function(x) identical(values[[1]], x)))
}
)
Unit: milliseconds
expr min median max
as.integer(y) == which(is.na(levels(y))) 8.566085 15.92278 46.45769
is.na(as.character(y)) 24.554066 29.05405 58.22167
y %in% NA 58.836131 64.57089 104.53393
is.na(levels(y)[y]) 29.748583 34.27200 131.22975
所以最好的办法可能是将第一种方法包装为我想的函数。差异不大。不幸的是,microbenchmark()
不会返回有关内存使用的任何信息。
问候 汤姆