R语言将变量分组的3种方法实例(含cut函数说明)
前言
在数据处理的过程中,我们有时候需要将连续的数值数据转换为类别数据,比如将收入分成高、中和低三组,将学生成绩分为优、良、中、及格和不及格五组。
本来将基于R语言,采用三种方法来实现;第一种是对变量直接进行重新赋值,第二种是使用within函数对语句进行组织,第三种是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(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)
这种方法较易理解,但使用attach函数可能会出现一些意想不到的问题,因此我们可以采用within函数,对代码进行优化,即方法二
方法二:使用within函数对变量进行分组
#方法二:使用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)
在方法二中,要注意within函数的写法,赋值语句要用大括号括起来,并且每条赋值语句占一行。此外,在第一行首先定义了 group2 <- NA这个变量。
方法三:采用cut函数
采用cut函数也是较为常用的一种方法,但要注意的是需要对间段点的开闭进行设定。
#方法三:采用cut函数 mathScore$group3 <- cut(mathScore$math, breaks = c(-Inf, 60, 70, 80, 90, Inf), labels = c("不及格","及格","中","良","优"), right=FALSE)
在cut函数中:
- breaks表示分界点,Inf表示无穷大; labels表示每个类别的名称;
- right=FALSE表示表示区间为左闭右开,即分段时不包括右边的点,即良为[80,90);right=TRUE则表示左闭右开区间(默认是这种情形)
我们执行mathScore代码,就可以看到三种方法得到的结果是一致的。
关于cut函数参数的补充说明:
cut函数有两个和分界点相关的参数,一个是include.lowest,一个是right,下面对这两个参数进行详细说明。
- right参数:right=TRUE表示左闭右开区间,right=FALSE表示左开右闭区间
- include.lowest参数:表示包括最小值或包括最大值
下面通过例子说明:
为了说明问题,我们把数据再重新定义一下,比原数据加入两行:
#重新定义一下数据框 mathScore <- data.frame(name=c("刘文涛","王宇翔","田思雨","徐丽娜","丁文彬","李志国","王智强","宋丽芳","袁芳芳","张建国","张志伟","李明"), math=c(85, 91, 74, 100, 82, 84, 78, 100, 51, 70, 0, NA)) head(mathScore)
我们把之前代码改写一下,把-Inf替换为0,把Inf替换为100,尝试一下结果:
#问题代码示例 mathScore$group <- cut(mathScore$math, breaks = c(0, 60, 70, 80, 90, 100), labels = c("不及格","及格","中","良","优"), right=FALSE) mathScore
我们可以看到输出的结果如下:
name math group1 刘文涛 85 良2 王宇翔 91 优3 田思雨 74 中4 徐丽娜 100 < NA >5 丁文彬 82 良6 李志国 84 良7 王智强 78 中8 宋丽芳 100 < NA >9 袁芳芳 51 不及格10 张建国 70 中11 张志伟 0 不及格12 李明 NA < NA >
此结果有问题,因为100分不包括在内,因为 right=FALSE是左闭右开区间,这时就要改写代码,加上参数include.lowest=TRUE
如下为正确代码示例:
#正确代码示例 mathScore$group <- cut(mathScore$math, breaks = c(0, 60, 70, 80, 90, 100), labels = c("不及格","及格","中","良","优"), right=FALSE, include.lowest=TRUE) mathScore
这时的结果如下,我们发现是结果正确的:
name math group1 刘文涛 85 良2 王宇翔 91 优3 田思雨 74 中4 徐丽娜 100 优5 丁文彬 82 良6 李志国 84 良7 王智强 78 中8 宋丽芳 100 优9 袁芳芳 51 不及格10 张建国 70 中11 张志伟 0 不及格12 李明 NA < NA >
因为right=FALSE是左闭右开区间,加上参数include.lowest=TRUE后,意为把最大值的右端点包括了。
为了深入了解两个端点参数的关系,我们尝试动下如下两段代码:
#对参数设置尝试的代码 mathScore$group <- cut(mathScore$math, breaks = c(0, 60, 70, 80, 90, 100), labels = c("不及格","及格","中","良","优"), right=TRUE, include.lowest=FALSE) mathScore
此代码为左闭右开区间,不包括最小值左侧端点;
#对参数设置尝试的代码 mathScore$group <- cut(mathScore$math, breaks = c(0, 60, 70, 80, 90, 100), labels = c("不及格","及格","中","良","优"), right=TRUE, include.lowest=TRUE) mathScore
此代码为左闭右开区间,包括最小值区间左侧端点。
因此,right和include.lowest总结如下:
right参数 | include.lowest参数 | 备注 |
---|---|---|
FALSE | TRUE | 左闭右开,包括最大值端点 |
TRUE | TRUE | 左开右闭,包括最小值端点 |
TRUE | FALSE | 左开右闭,不包括最小值端点 |
FALSE | FALSE | 左闭右开,包括最小值端点 |
其中,cut函数默认为right = TRUE, include.lowest=FALSE;
在实际的数据分析中,一般是将参数设置为right=FALSE, include.lowest=TRUE,即含下限不含上限,包括最大值区间右侧端点。
总结
关于R语言将变量分组的3种方法的文章就介绍至此,更多相关R语言变量分组内容请搜索编程教程以前的文章,希望以后支持编程教程!
下一章:详解R语言caret包trainControl函数
trainControl参数详解源码caret::trainControl <- function (method = "boot", number = ifelse(g ...