11

我有一个带有一堆分类变量的数据框。其中一些包含 NA,我使用该addNA函数将它们转换为显式因子级别。当我试图将它们视为他们似乎没有注册的 NA 时,我的问题就来了。

这是我的示例数据集并尝试“查找”NA:

df1 <- data.frame(id = 1:200, y =rbinom(200, 1, .5),
                  var1 = factor(rep(c('abc','def','ghi','jkl'),50)))
df1$var2 <- factor(rep(c('ab c','ghi','jkl','def'),50))
df1$var3 <- factor(rep(c('abc','ghi','nop','xyz'),50))

df1[df1$var1 == 'abc','var1'] <- NA

df1$var1 <- addNA(df1$var1)

df1$isNaCol <- ifelse(df1$var1 == NA, 1, 0);summary(df1$isNaCol)
df1$isNaCol <- ifelse(is.na(df1$var1), 1, 0);summary(df1$isNaCol)
df1$isNaCol <- ifelse(df1$var1 == 'NA', 1, 0);summary(df1$isNaCol)
df1$isNaCol <- ifelse(df1$var1 == '<NA>', 1, 0);summary(df1$isNaCol)

此外,当我键入时,??addNA我没有得到任何匹配项。这是灰色市场功能还是什么?任何建议,将不胜感激。

4

3 回答 3

5

请注意,这是调用addNA().

看看addNA()这些数据做了什么是有启发性的。

> head(df1$var1)
[1] <NA> def  ghi  jkl  <NA> def 
Levels: abc def ghi jkl
> levels(df1$var1)
[1] "abc" "def" "ghi" "jkl"
> head(addNA(df1$var1))
[1] <NA> def  ghi  jkl  <NA> def 
Levels: abc def ghi jkl <NA>
> levels(addNA(df1$var1))
[1] "abc" "def" "ghi" "jkl" NA

addNA正在改变因子的水平,使得缺失 ( NA) 是默认情况下 R 忽略它的水平,因为NA值所采用的水平当然是缺失的。它也在剥离NA信息——从某种意义上说,它不再是未知的,而是“缺失”类别的一部分。

来看看对addNA我们的帮助?addNA

如果我们查看 的定义,addNA我们会发现它所做的只是改变级别

of the factor, not changing the data any:

> addNA
function (x, ifany = FALSE) 
{
    if (!is.factor(x)) 
        x <- factor(x)
    if (ifany & !any(is.na(x))) 
        return(x)
    ll <- levels(x)
    if (!any(is.na(ll))) 
        ll <- c(ll, NA)
    factor(x, levels = ll, exclude = NULL)
}

请注意,它不会以其他方式更改数据 -NA仍然存在于因子中。addNA我们可以复制via的大部分行为:

with(df1, factor(var1, levels = c(levels(var1), NA), exclude = NULL))

> head(with(df1, factor(var1, levels = c(levels(var1), NA), exclude = NULL)))
[1] <NA> def  ghi  jkl  <NA> def 
Levels: abc def ghi jkl <NA>

但是,由于NA现在是一个级别,因此这些条目不会is.na()通过这说明您不工作的第二个比较(您使用的地方)表示为丢失is.na()

您从中获得的唯一好处addNA是,如果它已经作为一个级别存在,它就不会添加NA为一个级别。此外,如果数据中没有s,ifany您可以通过 停止将其添加为级别。NANA

您出错的地方是尝试NA使用通常的比较方法将 a 与某物进行比较(第二个示例除外)。如果我们不知道什么价值和NA观察值,我们怎么能把它和什么东西比较呢?好吧,我们不能,除了NA. 这是该函数所做的is.na()

> with(df1, head(is.na(var1), 10))
 [1]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE

因此我会做(根本不addNA 使用

df1 <- transform(df1, isNaCol = is.na(var1))

> head(df1)
  id y var1 var2 var3 isNaCol
1  1 1 <NA> ab c  abc    TRUE
2  2 0  def  ghi  ghi   FALSE
3  3 0  ghi  jkl  nop   FALSE
4  4 0  jkl  def  xyz   FALSE
5  5 0 <NA> ab c  abc    TRUE
6  6 1  def  ghi  ghi   FALSE

如果您希望将其作为1, ,0变量,只需添加as.numeric()

df1 <- transform(df1, isNaCol = as.numeric(is.na(var1)))

我认为你真正出错的地方是想要为NA这个因素附加一个水平。我认为addNA()这是一个方便的函数,可用于诸如 之类的东西table(),即使它也有不需要事先使用的论点addNA(),例如:

> with(df1, table(var1, useNA = "ifany"))
var1
 abc  def  ghi  jkl <NA> 
   0   50   50   50   50
于 2013-06-25T16:18:26.540 回答
5

NA使用通常的比较运算符测试相等性总是会产生NA---you want is.nais.na此外,调用factor测试每个级别索引(不是与该索引关联的值),因此您希望首先将 转换factorcharacter向量。

df1$isNaCol <- ifelse(is.na(as.character(df1$var1)), 1, 0);summary(df1$isNaCol)
于 2013-06-25T16:10:14.280 回答
4

任何与 NA 相比的都是 NA;这就是为什么您的第一个摘要都是不适用的原因。

addNA函数将您因子中的任何 NA 观察值更改为一个新的水平。然后这个级别被赋予标签NA(字符模式)。基础变量本身不再有任何 NA。这就是为什么您的第二个摘要全为 0 的原因。

要查看有多少观测值具有 NA 级别,请使用 Matthew Plourde 发布的内容。

于 2013-06-25T16:16:50.147 回答