1. 什么是因子 factor?

在R语言中,factor 叫做 因子类型

它主要用来表示 分类变量

比如:

这些变量不是连续数值,而是类别,所以适合用 factor


2. 创建普通字符变量

先创建一个性别变量。

gender <- c("男", "女", "女", "男", "男", "女")

gender
## [1] "男" "女" "女" "男" "男" "女"

查看类型:

class(gender)
## [1] "character"

此时结果是:

character

说明它现在只是字符型。


3. 把字符型转换成因子型

使用 factor() 函数。

gender_factor <- factor(gender)

gender_factor
## [1] 男 女 女 男 男 女
## Levels: 男 女

查看类型:

class(gender_factor)
## [1] "factor"

结果会是:

factor

查看因子的水平:

levels(gender_factor)
## [1] "男" "女"

这里的 levels 就是因子的类别。


4. factor 的基本语法

factor(x, levels = NULL, labels = NULL, ordered = FALSE)

常用参数:

参数 含义
x 要转换的变量
levels 指定类别顺序
labels 给类别重新命名
ordered 是否为有序因子

5. levels 是什么?

levels 表示因子的类别,也叫水平。

例如:

gender_factor <- factor(gender)

levels(gender_factor)
## [1] "男" "女"

R会自动按一定规则生成水平,比如:

女 男

但是很多时候,我们希望自己指定顺序。


6. 指定因子的水平顺序

例如我们希望顺序是:

男,女

可以这样写:

gender_factor2 <- factor(gender, levels = c("男", "女"))

gender_factor2
## [1] 男 女 女 男 男 女
## Levels: 男 女
levels(gender_factor2)
## [1] "男" "女"

这时因子的顺序就是我们指定的:

男 女

7. 为什么要指定 levels?

因为在绘图、排序、建模时,R会按照因子水平顺序显示。

比如我们创建一个数据框:

df <- data.frame(
  group = c("低", "中", "高", "低", "中", "高"),
  score = c(60, 75, 90, 65, 80, 95)
)

df
##   group score
## 1    低    60
## 2    中    75
## 3    高    90
## 4    低    65
## 5    中    80
## 6    高    95

查看结构:

str(df)
## 'data.frame':    6 obs. of  2 variables:
##  $ group: chr  "低" "中" "高" "低" ...
##  $ score: num  60 75 90 65 80 95

此时 group 可能是字符型。


8. 默认转换成因子

df$group_factor <- factor(df$group)

df
##   group score group_factor
## 1    低    60           低
## 2    中    75           中
## 3    高    90           高
## 4    低    65           低
## 5    中    80           中
## 6    高    95           高
levels(df$group_factor)
## [1] "低" "高" "中"

你可能会发现顺序不是你想要的。

例如R可能按字符顺序排列:

低 高 中

但是在逻辑上,我们希望顺序是:

低 中 高

9. 指定有意义的顺序

df$group_factor2 <- factor(df$group, levels = c("低", "中", "高"))

df
##   group score group_factor group_factor2
## 1    低    60           低            低
## 2    中    75           中            中
## 3    高    90           高            高
## 4    低    65           低            低
## 5    中    80           中            中
## 6    高    95           高            高
levels(df$group_factor2)
## [1] "低" "中" "高"

这样顺序就是:

低 中 高

10. 有序因子 ordered factor

如果类别本身有大小顺序,比如:

低 < 中 < 高

就可以设置为有序因子。

df$group_ordered <- factor(
  df$group,
  levels = c("低", "中", "高"),
  ordered = TRUE
)

df
##   group score group_factor group_factor2 group_ordered
## 1    低    60           低            低            低
## 2    中    75           中            中            中
## 3    高    90           高            高            高
## 4    低    65           低            低            低
## 5    中    80           中            中            中
## 6    高    95           高            高            高

查看类型:

class(df$group_ordered)
## [1] "ordered" "factor"

结果可能是:

ordered factor

查看是否有顺序:

df$group_ordered
## [1] 低 中 高 低 中 高
## Levels: 低 < 中 < 高

你会看到类似:

[1] 低 中 高 低 中 高
Levels: 低 < 中 < 高

11. 有序因子可以比较大小

因为 group_ordered 是有序因子,所以可以比较。

df$group_ordered > "低"
## [1] FALSE  TRUE  TRUE FALSE  TRUE  TRUE

结果中, 会是 TRUE, 是 FALSE。


12. labels:给类别改名字

有时候原始数据是数字编码:

1 = 男
2 = 女

我们可以用 labels 改成文字。

sex_code <- c(1, 2, 2, 1, 1, 2)

sex_factor <- factor(
  sex_code,
  levels = c(1, 2),
  labels = c("男", "女")
)

sex_factor
## [1] 男 女 女 男 男 女
## Levels: 男 女

查看水平:

levels(sex_factor)
## [1] "男" "女"

结果:

男 女

13. labels 示例:满意度

satisfaction_code <- c(1, 2, 3, 2, 1, 3, 3)

satisfaction <- factor(
  satisfaction_code,
  levels = c(1, 2, 3),
  labels = c("不满意", "一般", "满意"),
  ordered = TRUE
)

satisfaction
## [1] 不满意 一般   满意   一般   不满意 满意   满意  
## Levels: 不满意 < 一般 < 满意

查看结果:

levels(satisfaction)
## [1] "不满意" "一般"   "满意"
class(satisfaction)
## [1] "ordered" "factor"

结果中会显示:

不满意 < 一般 < 满意

14. 统计每个类别的频数

对于因子变量,经常需要统计各类别数量。

table(gender_factor2)
## gender_factor2
## 男 女 
##  3  3

也可以对数据框里的因子变量统计:

table(df$group_factor2)
## 
## 低 中 高 
##  2  2  2

15. 计算每个类别的平均值

比如我们想计算不同等级的平均分。

aggregate(score ~ group_factor2, data = df, mean)
##   group_factor2 score
## 1            低  62.5
## 2            中  77.5
## 3            高  92.5

结果类似:

  group_factor2 score
1            低  62.5
2            中  77.5
3            高  92.5

16. 因子在绘图中的作用

因子的顺序会影响图形横轴顺序。

先加载绘图包:

library(ggplot2)

如果没有安装,可以先运行:

install.packages("ggplot2")

17. 默认顺序的柱形图

ggplot(df, aes(x = group_factor, y = score)) +
  geom_col()

这里横轴顺序可能不是:

低 中 高

18. 指定顺序后的柱形图

ggplot(df, aes(x = group_factor2, y = score)) +
  geom_col()

这时横轴顺序就是:

低 中 高

所以:

如果图形顺序不对,通常要检查 factor 的 levels。


19. 因子在箱线图中的作用

ggplot(df, aes(x = group_factor2, y = score)) +
  geom_boxplot()

因为 group_factor2 是因子,所以R会把它当作分类变量处理。


20. 修改因子水平名称

假设现在有一个变量:

level <- factor(c("A", "B", "C", "A", "B"))

level
## [1] A B C A B
## Levels: A B C

查看水平:

levels(level)
## [1] "A" "B" "C"

可以直接修改:

levels(level) <- c("低级", "中级", "高级")

level
## [1] 低级 中级 高级 低级 中级
## Levels: 低级 中级 高级

注意:

修改的时候,新的名称要和原来的水平一一对应。


21. 增加新的因子水平

如果直接给因子赋一个不存在的新类别,可能会出问题。

f <- factor(c("A", "B", "A"))

f
## [1] A B A
## Levels: A B
levels(f)
## [1] "A" "B"

如果直接这样写:

f[1] <- "C"

可能会出现:

invalid factor level, NA generated

因为原来的水平只有:

A, B

没有 C

正确做法是先增加水平:

levels(f) <- c(levels(f), "C")

f[1] <- "C"

f
## [1] C B A
## Levels: A B C
levels(f)
## [1] "A" "B" "C"

22. 因子转字符

有时候我们不想让变量保持 factor 类型,可以转成字符型。

f_char <- as.character(f)

f_char
## [1] "C" "B" "A"
class(f_char)
## [1] "character"

23. 因子转数字的易错点

这是非常重要的考试易错点。

创建一个因子:

num_factor <- factor(c("10", "20", "30"))

num_factor
## [1] 10 20 30
## Levels: 10 20 30

如果直接转数字:

as.numeric(num_factor)
## [1] 1 2 3

你会发现结果不是:

10 20 30

而是类似:

1 2 3

为什么?

因为因子底层存储的是水平编号。


24. 因子正确转数字

应该先转字符,再转数字:

as.numeric(as.character(num_factor))
## [1] 10 20 30

结果才是:

10 20 30

记住:

as.numeric(factor变量)

得到的是因子编号,不一定是原始数字。

正确写法:

as.numeric(as.character(factor变量))

25. 删除未使用的因子水平

创建一个因子:

class_factor <- factor(
  c("一班", "一班", "二班"),
  levels = c("一班", "二班", "三班")
)

class_factor
## [1] 一班 一班 二班
## Levels: 一班 二班 三班
levels(class_factor)
## [1] "一班" "二班" "三班"

虽然数据中没有“三班”,但 levels 里仍然有“三班”。

如果想删除没有出现的水平:

class_factor2 <- droplevels(class_factor)

class_factor2
## [1] 一班 一班 二班
## Levels: 一班 二班
levels(class_factor2)
## [1] "一班" "二班"

26. 在数据框中删除未使用水平

students <- data.frame(
  class = factor(
    c("一班", "一班", "二班"),
    levels = c("一班", "二班", "三班")
  ),
  score = c(80, 85, 90)
)

students
##   class score
## 1  一班    80
## 2  一班    85
## 3  二班    90
levels(students$class)
## [1] "一班" "二班" "三班"

筛选出一班:

students_one <- students[students$class == "一班", ]

students_one
##   class score
## 1  一班    80
## 2  一班    85
levels(students_one$class)
## [1] "一班" "二班" "三班"

你会发现 levels 里可能还保留:

一班 二班 三班

删除未使用水平:

students_one$class <- droplevels(students_one$class)

students_one
##   class score
## 1  一班    80
## 2  一班    85
levels(students_one$class)
## [1] "一班"

27. ordered 和普通 factor 的区别

普通因子:

normal_factor <- factor(c("低", "中", "高"), levels = c("低", "中", "高"))

normal_factor
## [1] 低 中 高
## Levels: 低 中 高

有序因子:

ordered_factor <- factor(
  c("低", "中", "高"),
  levels = c("低", "中", "高"),
  ordered = TRUE
)

ordered_factor
## [1] 低 中 高
## Levels: 低 < 中 < 高

普通因子的 levels 显示为:

Levels: 低 中 高

有序因子的 levels 显示为:

Levels: 低 < 中 < 高

28. 检查一个变量是不是 factor

is.factor(gender_factor2)
## [1] TRUE
is.factor(gender)
## [1] FALSE

29. 因子常见考试题型

题型1:字符变量转因子

gender <- c("男", "女", "女", "男")

gender_f <- factor(gender)

gender_f
## [1] 男 女 女 男
## Levels: 男 女

题型2:指定因子顺序

grade <- c("中", "高", "低", "中", "高")

grade_f <- factor(grade, levels = c("低", "中", "高"))

grade_f
## [1] 中 高 低 中 高
## Levels: 低 中 高

题型3:创建有序因子

grade_ordered <- factor(
  grade,
  levels = c("低", "中", "高"),
  ordered = TRUE
)

grade_ordered
## [1] 中 高 低 中 高
## Levels: 低 < 中 < 高

题型4:数字编码转类别标签

code <- c(1, 2, 1, 3, 2)

code_f <- factor(
  code,
  levels = c(1, 2, 3),
  labels = c("低", "中", "高")
)

code_f
## [1] 低 中 低 高 中
## Levels: 低 中 高

题型5:统计各类别频数

table(code_f)
## code_f
## 低 中 高 
##  2  2  1

题型6:按类别计算均值

score_df <- data.frame(
  grade = factor(c("低", "中", "高", "低", "中", "高"),
                 levels = c("低", "中", "高")),
  score = c(60, 75, 90, 65, 80, 95)
)

aggregate(score ~ grade, data = score_df, mean)
##   grade score
## 1    低  62.5
## 2    中  77.5
## 3    高  92.5

30. 小练习

现在有一个学生数据:

student <- data.frame(
  id = 1:8,
  gender = c(1, 2, 1, 2, 1, 2, 1, 2),
  level = c("中", "高", "低", "中", "高", "低", "中", "高"),
  score = c(78, 90, 60, 82, 95, 65, 80, 88)
)

student
##   id gender level score
## 1  1      1    中    78
## 2  2      2    高    90
## 3  3      1    低    60
## 4  4      2    中    82
## 5  5      1    高    95
## 6  6      2    低    65
## 7  7      1    中    80
## 8  8      2    高    88

要求:

  1. gender 转换成因子,1表示男,2表示女;
  2. level 转换成有序因子,顺序是:低 < 中 < 高;
  3. 统计不同性别的人数;
  4. 统计不同水平的平均分;
  5. 画出不同水平的平均分柱形图。

31. 小练习参考答案

31.1 gender 转因子

student$gender_f <- factor(
  student$gender,
  levels = c(1, 2),
  labels = c("男", "女")
)

student
##   id gender level score gender_f
## 1  1      1    中    78       男
## 2  2      2    高    90       女
## 3  3      1    低    60       男
## 4  4      2    中    82       女
## 5  5      1    高    95       男
## 6  6      2    低    65       女
## 7  7      1    中    80       男
## 8  8      2    高    88       女

31.2 level 转有序因子

student$level_f <- factor(
  student$level,
  levels = c("低", "中", "高"),
  ordered = TRUE
)

student
##   id gender level score gender_f level_f
## 1  1      1    中    78       男      中
## 2  2      2    高    90       女      高
## 3  3      1    低    60       男      低
## 4  4      2    中    82       女      中
## 5  5      1    高    95       男      高
## 6  6      2    低    65       女      低
## 7  7      1    中    80       男      中
## 8  8      2    高    88       女      高

31.3 统计不同性别人数

table(student$gender_f)
## 
## 男 女 
##  4  4

31.4 统计不同水平平均分

level_mean <- aggregate(score ~ level_f, data = student, mean)

level_mean
##   level_f score
## 1      低  62.5
## 2      中  80.0
## 3      高  91.0

31.5 绘制平均分柱形图

ggplot(level_mean, aes(x = level_f, y = score)) +
  geom_col(fill = "skyblue") +
  labs(
    title = "不同水平的平均分",
    x = "水平",
    y = "平均分"
  )


32. 本节核心代码总结

# 字符转因子
f <- factor(c("男", "女", "男"))

# 指定因子顺序
grade <- factor(
  c("中", "高", "低"),
  levels = c("低", "中", "高")
)

# 有序因子
grade_ordered <- factor(
  c("中", "高", "低"),
  levels = c("低", "中", "高"),
  ordered = TRUE
)

# 数字编码转标签
sex <- factor(
  c(1, 2, 1),
  levels = c(1, 2),
  labels = c("男", "女")
)

# 查看因子水平
levels(sex)
## [1] "男" "女"
# 统计频数
table(sex)
## sex
## 男 女 
##  2  1
# 删除未使用水平
droplevels(sex)
## [1] 男 女 男
## Levels: 男 女
# 因子转字符
as.character(sex)
## [1] "男" "女" "男"
# 因子正确转数字
num_f <- factor(c("10", "20", "30"))
as.numeric(as.character(num_f))
## [1] 10 20 30

33. 一句话总结

因子 factor 的核心作用是:

把变量当作“分类变量”处理,并且可以通过 levels 控制类别顺序,通过 labels 修改类别名称,通过 ordered = TRUE 设置有序类别。

考试重点记住:

factor(x, levels = ..., labels = ..., ordered = TRUE)