【问题标题】:Unexpected behaviour of function table with "NaN" values具有“NaN”值的函数表的意外行为
【发布时间】:2016-03-08 08:04:39
【问题描述】:

最近,我在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 显示 NA 值,我会得到:

table(ex_vec, useNA="ifany")
#ex_vec
# Nan  NaN  Non  Oui <NA> 
#   1    1    2    1    1

因此,字符串"NaN"table 调用中被视为NA 值,而在输出中被视为非NA 值。

我知道(这会更好,并且)我可以通过将我的向量转换为 factor 来解决我的问题,但尽管如此,我真的很想知道这里发生了什么。有人有想法吗?

【问题讨论】:

  • 这只是基本用法......就像“为什么sum(c(1, NA))返回NA?” table(..., exclude = if (useNA == "no") c(NA, NaN), useNA = c("no", "ifany", "always")我不明白这些答案的目的
  • @rawr 解释为什么 string 被视为NaN 值?这不是被问到的用法,而是为什么。它比文档涵盖的 sum 示例不那么明显。 (我的意思是:NaN != "NaN"so 为什么要排除 "NaN",因为它不是排除向量的一部分)
  • @Tensibai,文档说exclude: levels to remove for all factors levels 不是NA 也不是NaN,它们是字符串..离开字符串试试table(1, exclude = 1)
  • @rawr 我清楚地明白这对你来说是显而易见的,根据这个问题分数(以及我自己的头抓来找出根本原因),这对每个人来说并不是那么明显......所以我确实认为答案会对其他人有所帮助。 (并且NA 是一个有效级别,即使不是字符串对象,但我明白你的意思NaN在字符向量中无效)
  • 大家安定下来!我认为发现这种行为令人困惑是合理的。 exclude 可以合理地解读为引用要排除的所提供向量的元素。因此,如果您告诉它排除 NaN(数字),它仍然会排除 "NaN"(字符),这可能会令人惊讶。

标签: r na


【解决方案1】:

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.

放心……

【讨论】:

  • 非常感谢您给出这个非常明确的答案(我也喜欢 factor doc 中的引述!)
【解决方案2】:

我想到的第一个想法是看一下table 定义,它的开头是:

> table
function (..., exclude = if (useNA == "no") c(NA, NaN), useNA = c("no", 
    "ifany", "always"), dnn = list.names(...), deparse.level = 1) 
{

听起来合乎逻辑,默认情况下,表不包括 NANaN

在表格代码中挖掘,我们看到如果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”作为排除向量,因为在比较之前被强制转换为字符。

【讨论】:

  • 感谢@Tensibai 的解释!为什么“NaN”在table 结果中仍然作为常规值排序,而不是以&lt;NA&gt; 结尾?
  • @CathG 因为级别是在创建时排序的;)请参阅levels 行的因子代码中的注释,一旦不排除它们成为正常条目
  • @CathG 当 table 参数设置为“no”以外的其他值时,它们不会被删除并视为没有特殊含义的普通字符串
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-27
相关资源
最近更新 更多