数值向量中的因子从其级别中每 100.000 个元素下降

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

考虑一个具有超过 100.000 个元素的

numeric
类型向量。在下面的示例中,它只是范围 1:500001。

n <- 500001
arr <- as.numeric(1:n)

以下

factor
调用序列会导致奇怪的行为:

首先调用

factor
,并将
levels
参数指定为与定义
arr
完全相同的范围。可以预见的是,结果变量恰好具有
n
水平:

> tmp <- factor(arr, levels=1:n)
> nlevels(tmp)
[1] 500001

现在再次调用

factor
获取之前的结果。结果是新值
tmp2
缺少其级别中的一些值:

> tmp2 <- factor(tmp)
> nlevels(tmp2)
[1] 499996 

检查缺少哪些项目,我们发现它是每 100.000 个元素(在本例中,其值等于其索引):

> which(!levels(tmp) %in% levels(tmp2))
[1] 100000 200000 300000 400000 500000 

减少

n
至 <=100.000 eliminates this unexpected behaviour. However, it occurs for any
n
> 100.000。

> n <- 99999
> arr <- as.integer(1:n)
> tmp <- factor(arr)
> tmp2 <- factor(tmp)
> nlevels(tmp2)
[1] 99999
> which(!levels(tmp) %in% levels(tmp2))
integer(0)

arr
向量具有
numeric
以外的类型时,也不会发生这种情况:

> n <- 500001
> arr <- as.integer(1:n)
> tmp <- factor(arr, levels=1:n)
> tmp2 <- factor(tmp)
> nlevels(tmp2)
[1] 500001

最后,当第一次调用

levels
时未指定
factor()
参数时,不会出现此问题。

什么可能导致这种行为?在 R 4.3.2 中测试

r r-factor
3个回答
9
投票

在第二次调用

factor
时,所有
NA
都不会记录为级别,例如

> factor(c(NA, 1))
[1] <NA> 1
Levels: 1

在您的情况下,您可以看到,级别在

NA
 中被识别为 
tmp

> tail(tmp)
[1] 499996 499997 499998 499999 <NA>   500001
500001 Levels: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ... 500001

> setdiff(levels(tmp), levels(tmp2))
[1] "100000" "200000" "300000" "400000" "500000"

所以在

tmp2
中,
NA
中的5个
tmp
(对应于
100000, 200000, 300000, 400000, 500000
)不会添加到
tmp2

的级别中

如果你在生成

levels = 1:n
时没有指定
tmp
,你会看到

> tail(tmp)
[1] 499996 499997 499998 499999 5e+05  500001
500001 Levels: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ... 500001

> tail(levels(tmp))
[1] "499996" "499997" "499998" "499999" "5e+05"  "500001"

如果

5e+05
中有
NA
而不是
tmp
,你自然就知道所有这些
NA
都是麻烦制造者。


5
投票

基于 ThomasIsCoding 的答案,这是由于科学记数规则适用于实数,但不适用于整数......

例如,在控制台中...

options(scipen = 0) #uses scientific notation if fewer characters than normal

500000L
[1] 500000   #integer displayed in normal notation

500000
[1] 5e+05    #numeric displayed in shorter scientific notation

因此,这些名称会导致使用数值的 100000 的每个倍数的因子水平不匹配。

问题可以通过增加

scipen
来解决。

我认为

scipen
主要是为了控制显示值,所以它被用于因子水平很奇怪。


0
投票

经过很好的解释,一个可能的解决方案是使用

gl

> n <- 500001
> tmp <- gl(n, 1)
> nlevels(tmp)
[1] 500001
> tmp2 <- factor(tmp)
> nlevels(tmp2)
[1] 500001
© www.soinside.com 2019 - 2024. All rights reserved.