因子转换为数值型背后发生了什么?

3

这里有一个小的data.frame

e = data.frame(A=c(letters[1:5], 1:5))

当我执行以下命令时,我有点困惑发生了什么:

unclass(e$A) %>% as.numeric()

我得到了以下输出:
 [1]  6  7  8  9 10  1  2  3  4  5

为什么 a:e 被视为 6:10

我认为这是因为1:5已经在数据中使用了,而函数试图在不引起歧义的情况下解析。不过我可能是错的。 - LAP
2个回答

8

data.frame 会创建一个因子,可以通过使用 str(e) 来查看:

'data.frame': 10 obs. of  1 variable:
 $ A: Factor w/ 10 levels "1","2","3","4",..: 6 7 8 9 10 1 2 3 4 5

这个因素有不同的级别,按字母顺序排序(其中R在字母前排序数字),levels(e$A)

 [1] "1" "2" "3" "4" "5" "a" "b" "c" "d" "e"

as.numeric函数将一个因子(factor)转换为各水平的指数值,即第一个水平得到值1(这意味着1保持不变),第六个水平得到值6(这意味着"a"变成了6)。

在这种情况下,您已经使用unclass()强制进行了此转换,从而产生了您看到的数字向量。 as.numeric只会删除levels属性。

?Comparison告诉我们,任何字符向量之间的比较(例如对它们进行sort排序)都基于当前语言环境的整理顺序。

注意:这与%>%操作符无关。


为什么数字排在字母前面?(我猜这就是提问者问题的主要原因) - agenis
你好,感谢回复。那这个怎么样?e1=data.frame(A=c(1:5,letters[1:5])),结果输出为1 2 3 4 5 6 7 8 9 10。 - dondapati
@agenis。是的,我的意图是找出为什么有数字优先级。如果您找到了任何信息,请更新评论,谢谢。 - dondapati
@user7462639,那个情况是一样的,级别总是按字母顺序重新排序,数字排在前面。 - Axeman

3
你的问题触及了每一种计算机语言内在的难题,那就是如何排序字符。
R帮助文件中的?sort表明:
“字符向量的排序顺序将取决于所使用的区域设置的整理序列:请参见比较。因子的排序顺序是它们级别的顺序。”
因此,你可以尝试找到所在的地区设置。你还需要检查国际字符串排序和比较规则的ISO 14651标准。根据你的位置,你可能会发现对于非常特定的字符排序会有不同,但是关于数字,我猜想它们总是排在最前面。
"a">"1"
#### [1] TRUE
"a">"A"
#### [1] FALSE

编辑: 关于大写字母和小写字母之间的字母优先级,它确实取决于您的系统区域设置(英语遵循us_en,非英语区域可以遵循ASCII或其他,请参见wikipedia段落)。尝试这个:

Sys.setlocale("LC_COLLATE", "C")
sort(c(1,2,3,"a", "b", "c", "A", "B", "C"))
#### [1] "1" "2" "3" "A" "B" "C" "a" "b" "c"
Sys.setlocale("LC_COLLATE", "French_France.1252")
sort(c(1,2,3,"a", "b", "c", "A", "B", "C"))
#### [1] "1" "2" "3" "a" "A" "b" "B" "c" "C"

类似的问题已经在这个问题中讨论过了。


1
嗨,你能检查一下这段代码吗: e1=data.frame(A=c(1:3,letters[1:3],LETTERS[1:3])) ;unclass(e1$A) %>% as.numeric()。输出结果是 1 2 3 4 6 8 5 7 9。因此理解为数字先出现,然后是字母,但是再次观察发现小写字母在大写字母之前。这违反了 "a">"A" 的规则。 - dondapati
就我所了解的,Unicode字符请参考以下链接:https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%88%97%E8%A1%A8。 - dondapati
1
R遵循哪个Unicode系统?对我的语法错误感到抱歉。 - dondapati

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