具有 "NaN" 值的函数 table 的意外行为
Unexpected behaviour of function table with "NaN" values
最近,我在 table
函数中遇到了一个与我预期不同的行为:
例如,让我们采用以下向量:
ex_vec <- c("Non", "Non", "Nan", "Oui", "NaN", NA)
如果我检查我的向量中的 NA
值,"NaN"
不被认为是一个(如预期的那样):
is.na(ex_vec)
# [1] FALSE FALSE FALSE FALSE FALSE TRUE
但是如果我尝试获取不同的值频率:
table(ex_vec)
#ex_vec
#Nan Non Oui
# 1 2 1
"NaN"
没有出现在table中。
但是,如果我 "ask" table
显示 NA
值,我会得到:
table(ex_vec, useNA="ifany")
#ex_vec
# Nan NaN Non Oui <NA>
# 1 1 2 1 1
因此,字符串 "NaN"
在 table
调用中被视为 NA
值,而在输出中被视为非 NA
值。
我知道(这会更好并且)我可以通过将我的矢量转换为 factor
来解决我的问题,但是尽管如此,我真的很想知道这里发生了什么。有人有想法吗?
我想到的第一个想法是看一下 table
定义,它的开头是:
> table
function (..., exclude = if (useNA == "no") c(NA, NaN), useNA = c("no",
"ifany", "always"), dnn = list.names(...), deparse.level = 1)
{
听起来合乎逻辑,默认情况下 table 排除 NA
和 NaN
。
在 table 代码中挖掘,我们发现如果 x
不是一个因素,它会将其强制为一个因素(这里没有什么新鲜事,文档中有说明)。
else {
a <- factor(a, exclude = exclude)
我没有发现任何其他可能影响将 "NaN"
强制转换为 NA
值的输入。
因此,我们正在寻找因素来找出根本原因:
> factor
function (x = character(), levels, labels = levels, exclude = NA,
ordered = is.ordered(x), nmax = NA)
{
[...] # Snipped for brievety
exclude <- as.vector(exclude, typeof(x))
x <- as.character(x)
levels <- levels[is.na(match(levels, exclude))] # defined in the snipped part above, is the sorted unique values of input vector, coerced to char.
f <- match(x, levels)
[...]
f
}
我们知道了,exclude 参数,即使是 NA
值也被强制转换为字符向量。
那么会发生什么:
> ex_vec <- c("Non", "Non", "Nan", "Oui", "NaN", NA)
> excludes<-c(NA,NaN)
> as.vector(excludes,"character")
[1] NA "NaN"
> match(ex_vec,as.vector(excludes,"character"))
[1] NA NA NA NA 2 1
我们匹配字符 "NaN" 作为排除向量,因为在比较之前被强制转换为字符。
当 factor
匹配向量的级别时,它会将其 exclude
列表转换为与输入向量相同的类型:
exclude <- as.vector(exclude, typeof(x))
所以如果您的排除列表有 NaN
并且您的向量是字符,则会发生这种情况:
as.vector(exclude, typeof(letters))
[1] NA "NaN"
哦,亲爱的。现在将排除真正的 "NaN"
个字符串。
要修复,请在 table
中使用 exclude=NA
(如果您正在制造可能会影响此的因素,则使用 factor
)。
我很喜欢 factor
的文档中的这个:
There are some anomalies associated with factors that have ‘NA’ as
a level. It is suggested to use them sparingly, e.g., only for
tabulation purposes.
安心...
最近,我在 table
函数中遇到了一个与我预期不同的行为:
例如,让我们采用以下向量:
ex_vec <- c("Non", "Non", "Nan", "Oui", "NaN", NA)
如果我检查我的向量中的 NA
值,"NaN"
不被认为是一个(如预期的那样):
is.na(ex_vec)
# [1] FALSE FALSE FALSE FALSE FALSE TRUE
但是如果我尝试获取不同的值频率:
table(ex_vec)
#ex_vec
#Nan Non Oui
# 1 2 1
"NaN"
没有出现在table中。
但是,如果我 "ask" table
显示 NA
值,我会得到:
table(ex_vec, useNA="ifany")
#ex_vec
# Nan NaN Non Oui <NA>
# 1 1 2 1 1
因此,字符串 "NaN"
在 table
调用中被视为 NA
值,而在输出中被视为非 NA
值。
我知道(这会更好并且)我可以通过将我的矢量转换为 factor
来解决我的问题,但是尽管如此,我真的很想知道这里发生了什么。有人有想法吗?
我想到的第一个想法是看一下 table
定义,它的开头是:
> table
function (..., exclude = if (useNA == "no") c(NA, NaN), useNA = c("no",
"ifany", "always"), dnn = list.names(...), deparse.level = 1)
{
听起来合乎逻辑,默认情况下 table 排除 NA
和 NaN
。
在 table 代码中挖掘,我们发现如果 x
不是一个因素,它会将其强制为一个因素(这里没有什么新鲜事,文档中有说明)。
else {
a <- factor(a, exclude = exclude)
我没有发现任何其他可能影响将 "NaN"
强制转换为 NA
值的输入。
因此,我们正在寻找因素来找出根本原因:
> factor
function (x = character(), levels, labels = levels, exclude = NA,
ordered = is.ordered(x), nmax = NA)
{
[...] # Snipped for brievety
exclude <- as.vector(exclude, typeof(x))
x <- as.character(x)
levels <- levels[is.na(match(levels, exclude))] # defined in the snipped part above, is the sorted unique values of input vector, coerced to char.
f <- match(x, levels)
[...]
f
}
我们知道了,exclude 参数,即使是 NA
值也被强制转换为字符向量。
那么会发生什么:
> ex_vec <- c("Non", "Non", "Nan", "Oui", "NaN", NA)
> excludes<-c(NA,NaN)
> as.vector(excludes,"character")
[1] NA "NaN"
> match(ex_vec,as.vector(excludes,"character"))
[1] NA NA NA NA 2 1
我们匹配字符 "NaN" 作为排除向量,因为在比较之前被强制转换为字符。
当 factor
匹配向量的级别时,它会将其 exclude
列表转换为与输入向量相同的类型:
exclude <- as.vector(exclude, typeof(x))
所以如果您的排除列表有 NaN
并且您的向量是字符,则会发生这种情况:
as.vector(exclude, typeof(letters))
[1] NA "NaN"
哦,亲爱的。现在将排除真正的 "NaN"
个字符串。
要修复,请在 table
中使用 exclude=NA
(如果您正在制造可能会影响此的因素,则使用 factor
)。
我很喜欢 factor
的文档中的这个:
There are some anomalies associated with factors that have ‘NA’ as
a level. It is suggested to use them sparingly, e.g., only for
tabulation purposes.
安心...