R无法将NaN转换为NA。

11

我有一个数据框,其中包含几列因子列,其中包含NaN,我想将其转换为NA(使用线性回归对象在新数据上进行预测时,NaN似乎会出问题)。

> tester1 <- c("2", "2", "3", "4", "2", "3", NaN)
> tester1 
[1] "2"   "2"   "3"   "4"   "2"   "3"   "NaN"
> tester1[is.nan(tester1)] = NA
> tester1 
[1] "2"   "2"   "3"   "4"   "2"   "3"   "NaN"
> tester1[is.nan(tester1)] = "NA"
> tester1 
[1] "2"   "2"   "3"   "4"   "2"   "3"   "NaN"

你可能想看一下data.table包中的setattr函数。还可以查看MatthewDowle在我今天早些时候提出的问题的答案:https://dev59.com/kWDVa4cB1Zd3GeqPhuiz - Matt Bannert
这个例子毫无意义:你打算如何在线性回归中使用字符数据? - Gavin Simpson
这是一个因子。据我上次检查,lm()可以处理因子。在示例周围加上factor()可能会更好。 - screechOwl
3个回答

21

问题在于:你的向量是字符类型,所以当然是“不是数字”的。这个最后一个元素被解释为字符串“NaN”。只有在向量是数值类型时使用 is.nan 才有意义。如果你想让字符型向量中的某个值缺失(以便回归函数正确处理),则可以使用(不带引号)NA_character_

> tester1 <- c("2", "2", "3", "4", "2", "3", NA_character_)
>  tester1
[1] "2" "2" "3" "4" "2" "3" NA 
>  is.na(tester1)
[1] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

无论是"NA"还是"NaN"都不算是字符向量中真正的缺失值。如果因某种原因一个因子变量中出现了"NaN"这样的值,那么你仍然可以使用逻辑索引:

既然您提到了这个问题,我想说,当我们在处理数据时,"NA"表示缺失的值,"NaN"则表示非数字的值。它们有着不同的含义和用途,需要根据具体情况进行区分。在字符向量中,它们实际上都不算是真正的缺失值。

如果因子变量中存在"NaN"这样的值,你可以使用逻辑索引来快速过滤掉这些值。例如:

tester1[tester1 == "NaN"] = "NA"  
# but that would not really be a missing value either 
# and it might screw up a factor variable anyway.

tester1[tester1=="NaN"] <- "NA"
Warning message:
In `[<-.factor`(`*tmp*`, tester1 == "NaN", value = "NA") :
invalid factor level, NAs generated
##########
tester1 <- factor(c("2", "2", "3", "4", "2", "3", NaN))

> tester1[tester1 =="NaN"] <- NA_character_
> tester1
[1] 2    2    3    4    2    3    <NA>
Levels: 2 3 4 NaN

最后的结果可能会让人感到惊讶。虽然仍有一个"NaN"级别,但其中没有任何元素是"NaN"。相反,之前为"NaN"的元素现在是一个真正的缺失值,在打印输出中表示为"."。


8

在这里,您不能在字符向量中使用 NaN,但这正是您现在所拥有的:

> tester1 <- c("2", "2", "3", "4", "2", "3", NaN)
> is.nan(tester1)
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
> tester1
[1] "2"   "2"   "3"   "4"   "2"   "3"   "NaN"

注意R认为这是一个字符串。
您可以在数字向量中创建NaN:
> tester1 <- c("2", "2", "3", "4", "2", "3", NaN)
> as.numeric(tester1)
[1]   2   2   3   4   2   3 NaN
> is.nan(as.numeric(tester1))
[1] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

当然,根据您的代码,R可以将NaN转换为NA
> foo <- as.numeric(tester1)
> foo[is.nan(foo)] <- NA
> foo
[1]  2  2  3  4  2  3 NA

7

编辑:

在评论中,Gavin Simpson提醒我,在您的情况下,有更简单的方法将实际上是“NaN”的内容转换为“NA”:

tester1 <- gsub("NaN", "NA", tester1)
tester1
# [1] "2"  "2"  "3"  "4"  "2"  "3"  "NA"

解决方案:

为了检测字符向量中哪些元素是NaN,您需要将向量转换为数值向量:

tester1[is.nan(as.numeric(tester1))] <- "NA"
tester1
[1] "2"  "2"  "3"  "4"  "2"  "3"  "NA"

说明:

这并不像你期望的那样工作,有几个原因。

首先,虽然NaN代表“不是数字”,但它确实具有"numeric"类,并且只在数字向量中才有意义。

其次,当NaN包含在字符向量中时,符号NaN会被悄无声息地转换为字符字符串"NaN"。当你测试它是否为nan时,字符字符串将返回FALSE

class(NaN)
# [1] "numeric"
c("1", NaN)
# [1] "1"   "NaN"
is.nan(c("1", NaN))
# [1] FALSE FALSE

这是一种非常迂回的方式将字符串“NaN”转换为“NA”。即使在他们的示例中尝试使用“NA”作为NA,这肯定不是OP想要的。 - Gavin Simpson
@GavinSimpson -- 好了,现在修好了。感谢你提醒我把注意力从细节中抽出来! - Josh O'Brien
我仍然认为你过于考虑了OP想要的内容。他想要将NaN转换为NA,而不是字符串版本,而是真正的R版本,分别表示非数字和缺失。忽略OP示例中的一个"NA" - 那是一个干扰项,我假设他们认为在字符向量中引用NA可能会起作用,或者类似于那样的东西。 - Gavin Simpson
@GavinSimpson -- 我知道你的意思,但OP在示例向量中也引用了所有整数,所以如果你是对的,那么有更多像是25条红鲱鱼。 (尽管现在提到NaN在线性回归中会出现问题使我认为你可能是对的)。 - Josh O'Brien
好的,字符串确实与此有很多关系。毕竟,提问者已经知道如何将NaN更改为NA(请参见问题的第4行!),但是并不理解NaN被静默转换为"NaN"。我想我们至少可以认为这个问题很令人困惑。干杯。 - Josh O'Brien
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接