考虑一个具有超过 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 中测试
在第二次调用
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
都是麻烦制造者。
基于 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
主要是为了控制显示值,所以它被用于因子水平很奇怪。
经过很好的解释,一个可能的解决方案是使用
gl
。
> n <- 500001
> tmp <- gl(n, 1)
> nlevels(tmp)
[1] 500001
> tmp2 <- factor(tmp)
> nlevels(tmp2)
[1] 500001