《R数据科学》第11章-用forcats处理因子
1. 简介
1.1 因子与分类变量
因子在 R 中用于处理分类变量。
分类变量是在固定的已知集合中取值的变量。如果仅在较小的集合内取值,那么这个变量就是分类变量。分类变量在 R 中通常保存为因子或字符向量。
当想要以非字母表顺序显示字符向量时,也可以使用分类变量。
1.2 准备工作(forcats 包)
forcats 包:提供了能够处理分类变量(其实就是因子的另一种说法)的工具,其中还包括了处理因子的大量辅助函数。
# 因为 forcats 不是 tidyverse 的核心 R 包,所以需要手动加载。
library(tidyverse)
library(forcats)
2. 创建因子
假设想要创建一个记录月份的变量:
2.1 直接用字符串来创建有什么问题?
x1 <- c("Dec", "Apr", "Jan", "Mar")
(1) 月份只有 12 个取值,如果输入错误,代码不会有任何反应。
x2 <- c("Dec", "Apr", "Jam", "Mar")
(2) 对月份的排序没有意义(按字母顺序排序)
sort(x1)
[1] "Apr" "Dec" "Jan" "Mar"
2.2 如何创建因子?
(1)先创建有效水平的一个列表(定义水平)
month_levels <- c(
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
)
(2)创建因子:factor()函数
功能:创建因子
用法:factor(x = character(), levels, labels = levels, exclude = NA, ordered = is.ordered(x), nmax = NA)
y1 <- factor(x1, levels = month_levels)
y1
[1] Dec Apr Jan Mar
Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
# 对y1排序
sort(y1)
[1] Jan Mar Apr Dec
Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
(3)注意事项(说明)
不在有效水平集合内的所有值都会自动转换为 NA
x2 <- c("Dec", "Apr", "Jam", "Mar")
y2 <- factor(x2, levels = month_levels)
y2
[1] Dec Apr <NA> Mar # "Jam"自动转换为 NA
Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
如果想要显示错误信息,可以使用 readr::parse_factor() 函数
y2 <- parse_factor(x2, levels = month_levels)
Warning: 1 parsing failure.
row col expected actual
3 -- value in level set Jam
如果省略了定义水平的这个步骤,会将按字母顺序排序的数据作为水平。
factor(x1)
[1] Dec Apr Jan Mar
Levels: Apr Dec Jan Mar
想让因子的顺序与初始数据的顺序保持一致
1. 在创建因子时,将水平设置为unique(x)
f1 <- factor(x1, levels = unique(x1))
f1
[1] Dec Apr Jan Mar
Levels: Dec Apr Jan Mar
2. 在创建因子后,对其使用 fct_inorder() 函数
f2 <- x1 %>% factor() %>% fct_inorder()
f2
[1] Dec Apr Jan Mar
Levels: Dec Apr Jan Mar
想直接访问因子的有效水平集合,可以使用 levels() 函数
levels(f2)
[1] "Dec" "Apr" "Jan" "Mar"
3. 综合社会调查
3.1 forcats::gss_cat 数据集
以该数据集为例,说明处理因子时经常遇到的一些问题。
简介:该数据集是综合社会调查(是美国芝加哥大学的独立研究组织 NORC 进行的一项长期美国社会调查)数据的一份抽样。
共包含9个变量
- year:调查年份,2000–2014
- age:年龄,最大89岁
- marital:婚姻状况
- race:人种
- rincome:收入
- partyid:党派关系
- relig:宗教信仰
- denom:教派
- tvhours:每天看电视时间gss_cat
# A tibble: 21,483 x 9
year marital age race rincome partyid relig denom tvhours
<int> <fct> <int> <fct> <fct> <fct> <fct> <fct> <int>
1 2000 Never m~ 26 White $8000 t~ Ind,nea~ Prot~ Sout~ 12
2 2000 Divorced 48 White $8000 t~ Not str~ Prot~ Bapt~ NA
3 2000 Widowed 67 White Not app~ Indepen~ Prot~ No d~ 2
4 2000 Never m~ 39 White Not app~ Ind,nea~ Orth~ Not ~ 4
5 2000 Divorced 25 White Not app~ Not str~ None Not ~ 1
6 2000 Married 25 White $20000 ~ Strong ~ Prot~ Sout~ NA
# ... with 21,477 more rows
3.2 查看因子水平
当因子保存在 tibble 中时,其水平不是很容易看到的。
(1)用count() 函数
gss_cat %>%
count(race)
# A tibble: 3 x 2
race n
<fct> <int>
1 Other 1959
2 Black 3129
3 White 16395
(2)用条形图
# 默认情况下, ggplot2 会丢弃没有任何数据的那些水平
ggplot(gss_cat, aes(race)) +
geom_bar()
# 添加 scale_x_discrete(drop = FALSE) 代码来强制显示这些水平
ggplot(gss_cat, aes(race)) +
geom_bar() +
scale_x_discrete(drop = FALSE)
4. 修改因子水平
4.1 fct_recode() 函数
功能:手动修改因子水平,可以对每个水平进行修改或重新编码
用法:fct_recode(.f, ...)
(1)查看 partyid 的水平
gss_cat %>% count(partyid)
# A tibble: 10 x 2
partyid n
<fct> <int>
1 No answer 154
2 Don't know 1
3 Other party 393
4 Strong republican 2314
5 Not str republican 3032
6 Ind,near rep 1791
7 Independent 4119
8 Ind,near dem 2499
9 Not str democrat 3690
10 Strong democrat 3490
对水平的描述太过简单,而且不一致。
(2)将 partyid 的水平修改为较为详细的排比结构(修改)
gss_cat %>%
mutate(partyid = fct_recode(partyid,
"Republican, strong" = "Strong republican",
"Republican, weak" = "Not str republican",
"Independent, near rep" = "Ind,near rep",
"Independent, near dem" = "Ind,near dem",
"Democrat, weak" = "Not str democrat",
"Democrat, strong" = "Strong democrat"
)) %>%
count(partyid)
# A tibble: 10 x 2
partyid n
<fct> <int>
1 No answer 154
2 Don't know 1
3 Other party 393
4 Republican, strong 2314
5 Republican, weak 3032
6 Independent, near rep 1791
7 Independent 4119
8 Independent, near dem 2499
9 Democrat, weak 3690
10 Democrat, strong 3490
(3)将多个原水平赋给同一个新水平(合并)
gss_cat %>%
mutate(partyid = fct_recode(partyid,
"Republican, strong" = "Strong republican",
"Republican, weak" = "Not str republican",
"Independent, near rep" = "Ind,near rep",
"Independent, near dem" = "Ind,near dem",
"Democrat, weak" = "Not str democrat",
"Democrat, strong" = "Strong democrat",
"Other" = "No answer",
"Other" = "Don't know",
"Other" = "Other party"
)) %>%
count(partyid)
# A tibble: 8 x 2
partyid n
<fct> <int>
1 Other 548
2 Republican, strong 2314
3 Republican, weak 3032
4 Independent, near rep 1791
5 Independent 4119
6 Independent, near dem 2499
7 Democrat, weak 3690
8 Democrat, strong 3490
4.2 fct_collapse() 函数
(4)合并多个水平
对于每个新水平,都可以提供一个包含原水平的向量。
gss_cat %>%
mutate(partyid = fct_collapse(partyid,
other = c("No answer", "Don't know", "Other party"),
rep = c("Strong republican", "Not str republican"),
ind = c("Ind,near rep", "Independent", "Ind,near dem"),
dem = c("Not str democrat", "Strong democrat")
)) %>%
count(partyid)
# A tibble: 4 x 2
partyid n
<fct> <int>
1 other 548
2 rep 5346
3 ind 8409
4 dem 7180