【上一篇:56.关于因子的四要素之创建因子】
【下一篇:58.关于学习因子的一个有用的数据集gss_cat】
处理因子,一方面可以用base R中的函数,还可以用forcats包(tidyverse的核心包之一)中的工具。与base R中的工具相比,forcats包中的工具使用起来更方便,因为函数名更规则,容易记忆和使用。
Base R中用于创建因子的函数是factor(),tidyverse中readr包用于解析因子的函数是parse_factor(),后者在解析异常的时候会打印警告信息。
为了便于对比记忆,两个函数的Usage如下:
factor(x = character(), levels, labels = levels,
exclude = NA, ordered = is.ordered(x), nmax = NA)
parse_factor(
x,
levels = NULL,
ordered = FALSE,
na = c("", "NA"),
locale = default_locale(),
include_na = TRUE,
trim_ws = TRUE
)
后者不能设置labels
factor()函数中:x为一个字符向量;levels用来指定因子的level,如果不指定这个参数,默认level的值是x中唯一值的集合(调用的是unique()函数),level的顺序是按照字母表顺序排序;labels:用来修改levels的值,要么是一个与levels长度一致的向量(顺序与levels是一 一对应的),要么是一个字符串(这种情况下,新的level值是该字符串后依次加上数字后缀);exclude:指定一个向量,最后形成的levels中不能包含指定的这些值;ordered:指定levels的顺序,在绘图中因子的顺序表示特别重要,但在回归模型中顺序特别特别重要;nmax:levels数量的上限,对非常大的x,有时候指定其唯一值的最大数量会很有用。
factor()函数的返回值是一个因子,是一个整数编码的集合,其长度与x的长度一致,其有一个重要属性--levels。
为什么说因子比字符向量好用?一个重要的原因是:单纯的字符串向量难以以一种有用的方式排序。对比如下:
# 字符串向量
> x1 <- c("Dec", "Apr", "Jan", "Mar")
# levels向量
> month_levels <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
# 直接对x1进行排序,除了按字母表顺序升序或降序排列之外,
# 很难按照我们的想法按照月份顺序排序
> sort(x1)
[1] "Apr" "Dec" "Jan" "Mar"
# 因子就不同了,因子已经按照月份顺序设定levels了,
# 所以sort排序的时候会按照x1中的值在levels中出现的顺序排了
> (y1 <- factor(x1, levels = month_levels))
[1] Dec Apr Jan Mar
Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
> sort(y1)
[1] Jan Mar Apr Dec
Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
上文之所以能那样对因子排序,实际是因为factor()函数在编码字符串的时候,将其存储为整数数字了,所以排序的时候实际上是按数字排序:
# 可以看到因子的存储模式是数字
> mode(y1)
[1] "numeric"
# 可以清楚地看到unique(x1)的值在levels中的位置
> as.numeric(y1)
[1] 12 4 1 3
后续我们更关系用forcats包里的函数处理因子排序、改变levels的值的问题。举个例子:如果想设置levels的顺序为x1中唯一值第一次出现的顺序,可以用两种方式:
> (f1 <- factor(x1, levels = unique(x1)))
[1] Dec Apr Jan Mar
Levels: Dec Apr Jan Mar
或者
> (f2 <- x1 %>% factor() %>% fct_inorder())
[1] Dec Apr Jan Mar
Levels: Dec Apr Jan Mar
fct_inorder()函数的功能就是:根据它们第一次出现的顺序排序factor的level
最后,levels()函数可以获得因子的levels属性信息,返回值是一个字符向量。
> levels(f1)
[1] "Dec" "Apr" "Jan" "Mar"
网友评论