R 中的因素:分类变量和连续变量

R 中的因子是什么?
R 中的因子 因子(Factor)是一种用于对数据进行分类和存储的变量,它具有有限数量的不同值。它将数据存储为整数值的向量。在 R 语言中,因子也称为分类变量,它同时存储字符串和整数数据值作为级别。因子主要用于 R 语言的统计建模和探索性数据分析。
从内部看,因子是由两个同时移动的对象组成的:一个编码整数向量和一个名为“字符属性”的字符。 各级每个代码都是该层级向量中的一个位置,这就是为什么打印一个因子会显示单词的原因。 取消分类() 显示数字。
在数据集中,我们可以区分两种类型的变量: 明确的 和 连续.
- 在 R 中对分类变量进行描述统计时,其值是有限的,通常基于特定的有限组。例如,R 中的分类变量可以是国家、年份、性别、职业。
- 然而,连续变量可以取任何值,从整数到小数。例如,我们可以有收入、股票价格等等。
这种区别值得注意,因为 R 会默默地为每种数据类型选择不同的默认值。数值列会用均值和中位数进行汇总,而因子列则会用每个级别的计数进行汇总。因此,将类别存储为文本或数字会改变你得到的分析结果。更广泛的存储模式集在指南中有所介绍。 R 数据类型和运算符.
分类变量
分类变量 R 数据存储为一个因子。让我们查看下面的代码,了解如何在 R 语言中将字符变量转换为因子变量。许多建模和机器学习程序无法直接处理原始文本,因此在拟合模型之前,必须将类别编码为级别或数字。
句法
factor(x = character(), levels, labels = levels, ordered = is.ordered(x))
R 基础参考文档中还记录了上述简略形式省略的另外两个论点: 排除这会先移除水平集构建之前的值,并且 n最大,限制了转换层数的上限,从而加快了超大向量的转换速度。
参数:
- x:R 语言中的分类数据向量。必须是字符串或整数,不能是小数。
- 各级:x 的可能取值向量。此参数为可选参数。默认值为向量 x 的所有元素的唯一列表,并按升序排列。
- 标签:在 R 中为 x 分类数据添加标签。例如,1 可以表示标签为男性,而 0 可以表示标签为女性。
- 排除:用于指定在形成水平集时要删除的值的向量。被排除的值在结果中变为 NA。
- 有序:一个逻辑标志,用于确定级别是否应按给定的顺序视为有序。
- n最大:层数的可选上限,对于长向量很有用。
计费示例:
让我们将字符向量转换为因子,并使用 class() 确认更改。
# Create gender vector gender_vector <- c("Male", "Female", "Female", "Male", "Male") class(gender_vector) # Convert gender_vector to a factor factor_gender_vector <-factor(gender_vector) class(factor_gender_vector)
输出:
## [1] "character" ## [1] "factor"
类从字符型切换到了因子型,但打印值没有任何变化。转换很重要。 绳子 在 R 中,在进行机器学习任务之前,将其转换为因子变量,因为此时类别才成为一个固定的、经过验证的集合。
R 中的分类变量可以分为 名义分类变量 和 序数分类变量.
名义分类变量
名义分类变量可以有多个值,但顺序无关紧要。例如,男性或女性。R 语言中的名义分类变量不包含任何顺序信息。
# Create a color vector color_vector <- c('blue', 'red', 'green', 'white', 'black', 'yellow') # Convert the vector to factor factor_color <- factor(color_vector) factor_color
输出:
## [1] blue red green white black yellow ## Levels: black blue green red white yellow
从 factor_color 的值中,我们无法判断顺序。级别列表之所以按字母顺序排列,仅仅是因为没有提供 levels 参数,所以 R 自行对唯一值进行了排序。这种排序遵循的是当前区域设置,而不是纯 ASCII 码,这也是为什么在顺序至关重要时,需要显式指定级别的原因之一。
序数分类变量
有序分类变量确实具有自然的顺序。这种顺序来源于传递给函数的向量的顺序。 各级 参数 `ordered` 设置为 `TRUE` 会告诉 R 将该序列视为排序序列而非普通列表。设置 `ordered` 为 `FALSE` 并不会反转排序,它只会生成一个普通的无序因子。要从高到低排序,只需反转 `levels` 向量本身即可。
计费示例:
我们可以使用 summary 来计算 R 中每个因子变量的值。
# Create Ordinal categorical vector day_vector <- c('evening', 'morning', 'afternoon', 'midday', 'midnight', 'evening') # Convert `day_vector` to a factor with ordered level factor_day <- factor(day_vector, order = TRUE, levels =c('morning', 'midday', 'afternoon', 'evening', 'midnight')) # Print the new variable factor_day
输出:
## [1] evening morning afternoon midday
midnight evening
控制台首先打印数值,然后打印排名。下一个代码块以 Levels 行开头,该行仍然被注释掉,因此排名会保持可见,同时 summary() 调用会附加到之前的代码中。
## Levels: morning < midday < afternoon < evening < midnight # Append the line to above code # Count the number of occurence of each level summary(factor_day)
输出:
## morning midday afternoon evening midnight ## 1 1 1 2 1
R 按照 levels 参数的指定顺序,将颜色级别从“早晨”到“午夜”排序。由于该因子是有序的,因此诸如 < 和 > 之类的比较运算符也适用于它,而这些运算符对上述名义颜色因子则无效。
连续变量
在 R 语言中,连续型变量是默认值,它们以数值或整数形式存储。我们可以从下面的数据集中看出这一点。mtcars 是一个内置数据集,它收集了不同类型汽车的信息。我们可以使用 `mtcars` 导入该数据集,并检查变量 `mpg`(每加仑行驶里程)的类型。它返回一个数值,表明这是一个连续型变量。
dataset <- mtcars class(dataset$mpg)
输出
## [1] "numeric"
并非所有数值列都是真正连续的。在同一数据集中,`cyl` 列只包含 4、6 和 8,而 `am` 列只包含 0 和 1,因此它们都是恰好以数字形式存储的类别。在建模之前使用 `factor()` 函数将它们转换为连续值,可以防止 R 将 4 缸和 6 缸之间的间隙视为测量值。相反的操作,即把连续列分割成多个区间,则由 `cut()` 函数处理。
R语言中的因子水平和标签
levels 属性是您需要花费最多时间调整的部分,因为它既控制哪些内容会被打印出来,也控制模型将什么视为基线。四个基本的 R 辅助函数几乎可以涵盖所有情况。
| 功能 | 它做什么 | 典型用途 |
|---|---|---|
| 层级(f) | 读取或替换关卡名称 | 将缩写重命名为易于理解的标签 |
| nlevels(f) | 返回级别数 | 检查类别在连接后是否没有爆炸 |
| 重新调整(f, ref) | 向前移动一层 | 选择回归基准 |
| droplevels(f) | 移除观测值为零的层级。 | 子集或筛选后的清理工作 |
下面的代码块将这四个因素应用于之前创建的颜色和性别因素。
# Inspect the levels of an existing factor levels(factor_color) # the level names, in the order R stored them nlevels(factor_color) # how many distinct levels exist # Rename the levels in place (the new vector must follow the same order) levels(factor_color) <- c('Black', 'Blue', 'Green', 'Red', 'White', 'Yellow') # Attach labels at creation time instead of renaming afterwards gender_coded <- factor(c(1, 0, 0, 1, 1), levels = c(0, 1), labels = c('female', 'male')) # Make 'male' the reference level that modelling functions compare against gender_coded <- relevel(gender_coded, ref = 'male') # Remove levels that survived a subset but no longer occur in the data subset_color <- droplevels(factor_color[1:3])
有两个细节值得注意。`levels()` 函数会按位置重命名,因此不匹配的向量会悄悄地将类别重新标记。此外,子集会保留每个原始级别,直到调用 `droplevels()` 函数为止,这就是为什么过滤后的值会受到影响的原因。 数据框 仍然可以绘制空柱状图。 标签 参数又有所不同:它在创建时命名级别,重复的标签会将多个输入值合并到一个级别中。
如何在 R 语言中将因子转换为数值或字符型
这是 R 语言中最常见的因子错误。因为因子存储的是整数代码,所以对其调用 `as.numeric()` 函数会返回这些代码,而不是屏幕上显示的值。例如,2021 年至 2023 年的因子会返回 1、2 和 3。
# A factor whose labels happen to look like numbers year_factor <- factor(c('2021', '2023', '2022', '2023')) # WRONG: this returns the internal codes 1, 3, 2, 3 - not the years as.numeric(year_factor) # RIGHT: read the label through the levels attribute first as.numeric(levels(year_factor))[year_factor] # Equivalent and easier to remember, but slightly slower as.numeric(as.character(year_factor)) # Back to plain text as.character(year_factor)
R 基础文档推荐使用 `as.numeric(levels(f))[f]` 作为正确且稍快的写法,而 `as.numeric(as.character(f))` 则是更易读的等效写法。两者都先读取标签,然后再进行转换。
- 性格因素as.character(f) 将标签作为纯文本返回。
- 因式分解为整数代码: 当代码正是你想要的时,可以使用 as.integer(f) 或 unclass(f)。
- 因素: factor(x) 或更快的 as.factor(x) 快捷方式。
- 数值因子: factor(x) 用于离散码,cut(x, breaks) 用于需要分段的连续值。
所有这些方法都适用一项安全措施。如果 x 中的某个值未出现在 levels 向量中,factor() 函数会将该元素设置为 NA 而不是引发错误,因此多余的空格或大小写差异可能会导致行被悄悄删除。比较转换前后的唯一值,或者 对数据框进行排序 在新栏目中,问题很快就暴露出来了。
R 语言中因子型、字符型和数值型:何时使用哪种类型
尽早选择存储模式可以大大减少后续的调试工作。下表比较了文本或代码列可以采用的三种模式。
| 特性 | 因素 | 字符 | 数字 |
|---|---|---|---|
| 存储为 | 整数代码加上一个级别属性 | 琴弦 | Doubles 或整数 |
| 固定值集 | 是的,按级别划分。 | 没有 | 没有 |
| 自定义显示顺序 | 是的,通过各个层面。 | 仅按字母顺序排列 | 仅限数字 |
| 算术 | 不允许 | 不允许 | 允许 |
| 模型对比 | 自动构建 | 先是被迫的 | 被视为一种测量 |
使用 因素 当值来自已知的封闭列表、显示或排名顺序很重要,或者列为模型或图表图例提供数据时,请使用此方法。 字符 适用于自由文本、标识符以及任何需要解析或连接的内容,例如名称、备注和不断更新的值的代码。 数字 只有当两个值之间的距离有意义时才适用。
下面这个方框展示了检查你实际拥有什么的最快方法。
# Ask R what each column of a data frame actually is sapply(mtcars, class) # Direct membership tests is.factor(factor_day) is.ordered(factor_day) # unclass() exposes the integer codes hiding behind the labels unclass(factor_color)
两个习惯可以确保选择的准确性。每次导入后都运行 `sapply(df, class)`,因为数值列中哪怕只有一个多余的字符都会将整列转换为文本。并且尽可能晚地将数据转换为因子,最好在数据清理和合并之后再进行转换。 dplyr 连接和筛选仍然比较的是普通字符串,而不是不匹配的级别集。
