R语言将连续数值变量分组为类别的3种方法详解

宋时安
宋时安
发布时间:2026-10-15| 3人浏览过
原创

在数据处理过程中,经常需要将连续的数值数据转换为类别数据,例如将成绩划分为优、良、中、及格和不及格。本文将介绍在R语言中使用直接索引赋值、within()函数以及cut()函数进行变量分组的三种方法,并详细解析cut函数的区间控制参数与常见误区。

准备数据

首先构建一个包含学生姓名和数学成绩的示例数据框:

# 定义数据框
mathScore <- data.frame(
  name = c("刘文涛","王宇翔","田思雨","徐丽娜","丁文彬",
           "李志国","王智强","宋丽芳","袁芳芳","张建国"),
  math = c(85, 91, 74, 100, 82, 84, 78, 100, 51, 70)
)
head(mathScore)

接下来以90、80、70和60为界,将学生的数学成绩分为优、良、中、及格和不及格五类。

方法一:对变量直接进行赋值

通过逻辑索引对新生成的列进行逐个赋值。注意,attach()虽然方便访问列名,但容易引发命名冲突,操作完毕后需用 detach() 恢复环境。

# 方法一:直接对分组变量进行赋值
attach(mathScore)
mathScore$group1[math >= 90] = "优"
mathScore$group1[math >= 80 & math < 90] = "良"
mathScore$group1[math >= 70 & math < 80] = "中"
mathScore$group1[math >= 60 & math < 70] = "及格"
mathScore$group1[math < 60] = "不及格"
detach(mathScore)
head(mathScore)

方法二:使用 within 函数组织代码

within() 函数允许在一个数据框的作用域内执行多条表达式,无需挂载整个数据集,代码更整洁且避免了命名空间污染。注意初始化新变量(如赋值为NA),确保赋值语句块正确包裹。

# 方法二:使用 within 函数对变量进行分组
mathScore <- within(mathScore, {
  group2 <- NA
  group2[math >= 90] = "优"
  group2[math >= 80 & math < 90] = "良"
  group2[math >= 70 & math < 80] = "中"
  group2[math >= 60 & math < 70] = "及格"
  group2[math < 60] = "不及格"
})
head(mathScore)

方法三:采用 cut 函数

cut() 是处理分箱最常用且高效的函数。其核心在于正确设置断点(breaks)、标签(labels)及区间的开闭属性。

# 方法三:采用 cut 函数
# breaks 表示分界点,Inf表示无穷大; labels表示每个类别的名称
# right=FALSE 表示左闭右开区间,例如 良为 [80, 90)
mathScore$group3 <- cut(
  mathScore$math,
  breaks = c(-Inf, 60, 70, 80, 90, Inf),
  labels = c("不及格","及格","中","良","优"),
  right = FALSE
)

关于 cut 函数参数的关键说明:

  • breaks:用于指定分割点的向量。
  • right:决定区间是左闭右开还是左开右闭。
    - right=TRUE(默认):左开右闭区间 (a, b]。
    - right=FALSE:左闭右开区间 [a, b)。
  • include.lowest:当设置为 TRUE 时,强制包括最小值或最大值所在的端点,解决因区间开闭导致的边界遗漏问题。

处理实际边界的注意事项

在实际数据中,若未使用无穷大作为边界,或者遇到极值恰好落在区间断点上,必须结合 include.lowest 使用,否则超出范围的值会变为 NA。

为了演示,向数据中添加极端值:

# 重新定义一下数据框
mathScore_test <- data.frame(
  name = c("刘文涛","王宇翔","田思雨","徐丽娜","丁文彬",
           "李志国","王智强","宋丽芳","袁芳芳","张建国","张志伟","李明"),
  math = c(85, 91, 74, 100, 82, 84, 78, 100, 51, 70, 0, NA)
)
head(mathScore_test)

如果直接将断点设为实际范围而不加控制:

# 潜在的问题代码示例
mathScore_test$group_bad <- cut(
  mathScore_test$math,
  breaks = c(0, 60, 70, 80, 90, 100),
  labels = c("不及格","及格","中","良","优"),
  right = FALSE
)
mathScore_test

在上述 right=FALSE(左闭右开 [0, 60), [60, 70)... [90, 100))的情况下,分数为100的学生被划到了组外(显示为 NA),因为100不包含在最后一个区间内。同样,0分会进入不及格组,但如果区间设定有变也可能出现遗漏。

修复后的正确写法:

# 加上 include.lowest = TRUE 修正边界问题
mathScore_test$group_correct <- cut(
  mathScore_test$math,
  breaks = c(0, 60, 70, 80, 90, 100),
  labels = c("不及格","及格","中","良","优"),
  right = FALSE,
  include.lowest = TRUE  # 确保最大值等边界值能正确归入组别
)
mathScore_test

此时可以看到100分成功归类为“优”。

参数组合逻辑总结

right 参数 include.lowest 参数 效果备注
FALSE TRUE 左闭右开,且强制包括最大值的右侧端点
TRUE TRUE 左开右闭,且强制包括最小值的左侧端点
TRUE FALSE 左开右闭,不包括两端极限值
FALSE FALSE 左闭右开,不包括两端极限值

通常建议在R语言中设置 right=FALSE 且 include.lowest=TRUE,这样可以实现按“含下限不含上限”的逻辑分箱,同时保证数据的最大值不会被遗漏。

总结

以上是关于R语言中将连续数值变量分为不同类别的3种方法的详细内容,更多关于R语言变量分组切割的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。