使用 addNA() 后查找 NA 值

问题描述 投票:0回答:4

我有一个包含一堆分类变量的数据框。其中一些包含 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
时,我没有得到任何匹配项。这是灰市功能还是什么?任何建议将不胜感激。

r categories na
4个回答
5
投票

使用常用的比较运算符测试与

NA
的相等性总是会产生
NA
——您想要
is.na
。此外,在
is.na
上调用
factor
会测试每个级别索引(而不是与该索引关联的值),因此您需要首先将
factor
转换为
character
向量。

df1$isNaCol <- ifelse(is.na(as.character(df1$var1)), 1, 0);summary(df1$isNaCol)

5
投票

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

之前
使用 OP 的数据完成的。

看看

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

 正在改变因子的 
levels,使得缺失值 (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
 的大部分行为:

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

 现在是一个级别,这些条目
not 通过 is.na()
 指示为缺失,这解释了您无法进行的第二个比较(在您使用 
is.na()
 的地方)。

addNA

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

你出错的地方是尝试使用常用的比较方法(除了你的第二个例子)将

NA

与某些东西进行比较。如果我们不知道观察的价值和
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
    

4
投票
任何与 NA 相比的东西都是 NA;这就是为什么你的第一个总结完全不适用。

addNA

函数将因子中的任何 NA 观察值更改为新水平。然后,该级别被赋予 
label NA(字符模式)。基础变量本身不再具有任何 NA。这就是为什么你的第二个总结全是0。

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


0
投票
我很惊讶这么简单的问题却没有简单的答案。我遇到了同样的情况,我的数据管道子集需要 NA 级别。事实证明

is.na()

 适用于水平,但不适用于因子变量本身。所以我的解决方案是基于此。

set.seed(1) x <- factor(sample(c(0,1,NA), size = 10, replace = T)) x #[1] 0 <NA> 0 1 0 <NA> <NA> 1 1 <NA> #Levels: 0 1 x <- addNA(x) x #[1] 0 <NA> 0 1 0 <NA> <NA> 1 1 <NA> #Levels: 0 1 <NA> # get the level that is NA na_level <- which(is.na(levels(x))) # 3 # get a logical equivalent of is.na() before using addNA() !x %in% (levels(x)[-na_level]) # [1] FALSE TRUE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE
    
© www.soinside.com 2019 - 2024. All rights reserved.