彻底理解R中factor的本质
factor的本质(怎么存的)
x <- factor(c("a", "b", "b", "a"))
x
#> [1] a b b a
#> Levels: a b
typeof(x)
#> [1] "integer"
attributes(x)
#> $levels
#> [1] "a" "b"
#>
#> $class
#> [1] "factor"
基础数据类型是integer vector. class为factor, 还有levels attribute. levels attribute对于factor非常重要, 应该是一个vector是不是factor的本质区别. 要理解这一点, 见下一节.
factor的原理: levels属性
举个例子:
a=c(4,5,4,64) # 就算改成a=as.character(c(4,5,4,64)), 也完全没区别.
factor_a=as.factor(a) # 改成factor, 输出也完全一样
as.integer(factor_a) # [1] 1 2 1 3
levels(factor_a) # [1] "4" "5" "64"
其实factor如[[#^74A6Ux]]所说, 就是integer, 并且它原来就算是integer, 也与之后的integer完全无关, 它会数有多少个不同取值, 假设是n, 那么它会建立一个映射. 比如这里有3个不同值, 4, 5, 64, 它对不同值排序, 确定映射: 1->"4", 2->"5", 3->"64". 注意, 它根本不在意原vector类型是什么, 在确定映射前, 都会转换为字符串.
levels, 所存的就是这样一个映射, 它是character vector. vector天然建立了数->字符串的映射.
存1 2 1 3, 映射又是"4" "5" "64", 那么显示就是"4" "5" "4" "64".
对factor调用as.integer(), as.vector(), as.character()
as.integer()是返回底层的integer, as.numeric()和as.integer()返回相同, as.vector调用起来和as.character差不多, 都是返回levels映射后的显示.
a=c(4,5,4,64)
factor_a=as.factor(a) # 改成factor, 输出也完全一样
as.integer(factor_a) # [1] 1 2 1 3
levels(factor_a) # [1] "4" "5" "64"
ordered, levels参数
首先, ordered也是一个class. 看例子:
status <- c("Poor", "Improved", "Excellent", "Poor")
status <- factor(status, ordered=TRUE)
print(class(status)) # [1] "ordered" "factor"
有时候你也会看到order参数, 别信, 你知道R就是可以参数不写全的, order就是ordered, 只是没把参数写全.
如果给了levels, 那么ordered就是levels这个顺序, 从小到大.
如果没给levels, 就是字符排序后的结果. 比如"1"<"2"<"3"
.
比如上面这个例子, 就会是字符排序, Poor会对应3, Improved会对应2, Excellent会对应1. 因为字符序如此.
事实上也的确如此:
levels(status) # [1] "Excellent" "Improved" "Poor"
factor的levels, labels参数
如果又出现了levels又出现了labels, 会怎样?
这样的话, levels倒不是完全没用, 它有两个作用: 1. 配合ordered使用. 2.或者给出可能值, 这样就算向量没有取遍, levels可以给遍全部值.
但创建完, 它就没用了, 无论是底层值, 还是levels属性, 都再也没存当初的levels参数了. labels存的, 才是之后levels属性会存的, 并且它和levels参数对应. 看这个例子:
> a=factor(c("b", "a", "a"),levels=c("b","c","a"),ordered=T, labels=c("bat","cat","ar"))
> as.vector(a)
[1] "bat" "ar" "ar"
> as.numeric(a)
[1] 1 3 3
> levels(a)
[1] "bat" "cat" "ar"