当前课程知识点:R语言数据分析 > 中部:执具 > 第7章 数据对象——面向数据对象学习R语言 > 7.2 向量与因子(II)
大家好
欢迎来到《R语言数据分析》课程
今天继续与大家交流
向量与因子的第二部分内容
先回到我们的数据对象地图
在咱们这门课里面
将需要重点掌握的
数据对象分成三组六类
在上一次课里面将这个第一组里面的
向量我们做了一个简要的交流
今天我们来看一下第二种这个因子
从测量的尺度来讲
根据这个量化程度不一样
我们可以将变量分成四种类型
第一种是定类
第二种是定序
(第三种是)定距
(第四种是)定比
这么四种
所谓定类
它其实只能是什么
(只能)判断是否相同
比如说张三李四
他性别分别是男是女
这个时候可以把张三和男划上等号
比如说李四是女
这个时候就是李四等于女
从这个数学性质上来讲
只能说是= ≠
毫无疑问
对于性别也好
人种也好
我们只能区分这个类别
并不能说男尊女卑
也不能说某一个人种优于另外一个人种
所以这个时候只能划等号 或者是不等号
大于号小于号是没有意义的
假如我们要划这个大于号或者小于号的话
只能对什么
对这种定序变量才有这个意义
比如说我们碰到的等级 规模等等
这些其实就有意义了
比如说我这个星级酒店
四星级比三星级要好
三星级有比二星级的酒店好
这个时候就可以划什么
大于号小于号
将这个顺序给排出来
当然对这个定序变量来讲
虽然我们在等于号不等于号基础之上
我们进一步可以划大于号小于号
但是我们并不能给它进行
这个加减乘除这种四则运算
我们不能说这个星级酒店
四星级酒店
加个三星级酒店就变成了 七星级
所以这个时候只能划大于小于
假如要做这个四则运算的话
它最起码要是什么
要是这个定距的变量
比如说我们摄氏温度
它就是一个定距的变量
它可以什么
它可以确定这个差别
比如我们中午的温度是30度
凌晨的温度是15度
那毫无疑问
这个时候中午就比什么
凌晨的温度高15度
这个时候
这个差别可以确定了
这是我们量化程度
到了这第三个层级
就是可以确定差别的这种定距的变量
当然即便是温度
它可以确定差别
可以做这个加减这个运算
但是它不能做这个乘除运算
什么意思
我们不能说中午的温度是30度
然后凌晨的温度15度
我就说中午比凌晨
是它的两倍热
这是没有意义的
同时这边也没有一个绝对的零点
我们不能说零度是没有温度
其实零度还是一个温度的
假如我们要说它既有绝对的零点
同时又能做这个乘除运算的话
那它必须是什么
它必须是定比的变量
比如说薪资 长度 等等
它既有绝对的0点
0表示什么都没有
同时也可以做乘除的运算
这就是我们从这个量化的程度来讲
它可以分成这种
定类 定序 定距 定比四种类型
具体到我们R语言里面来讲
我们通过哪些数据对象
来存储这四种类型的变量
这前面两种无论是定类也好 定序也好
它都属于类别变量
我们通过这个因子
也是今天我们开始要讲的这个因子
这么一种数据对象来存储的
对于我们后面这两种定距或者定比
这两种变量我们通过什么
通过我们前面讲的向量来进行存储
假如是定类的话
我们在R语言里面就是一个无序因子
假如是定序的话
这个时候就相应的就是一个
有序因子进行存储
我们归纳一下
向量和因子其实它区别是什么
向量主要是什么
用于存储这个数值变量
因子用于存储这个类别变量
无论是定类的也好 还是定序的
定类的话就是类别变量 就是无序因子
然后定序的话就是有序因子
作为类别变量来讲
我们一般来说
它的那个取值的类别是有限的
比如说我们有1万个学生
这个时候它只有两个性别
一个男一个女
这个取值的水平它只有两种
在我们R语言里面我们称这个类别就是什么
就是这个levels 就是水平
一般来讲 取值水平(的个数)会远远小于
我们的观测对象的个数
引入这个因子
我们既可以从这个存储的方式来讲
也可以从这个数据分析的角度来看待
这个因子这个数据对象的引入
从这个存储方式来讲
它其实比我们一般的
这个字符这种存储的方式更加有效
什么意思
在本质上它存储为什么
存储为一个整型的向量
比如说我现在有1万个学生
男 女 男 女 男 女……
它实际上存储什么
在我们内存里面
他存储为1 2 …1 2这么一个
整型的一个数值的向量
在数据分析而言
我们在R语言里面
在后续的课程里面会讲到
就是这个因子的话
它在很多应用场景里面
都是有一个实际的用途的
比如说我们做分组统计的时候
因子怎么样
常常用来做这个分组变量
对于我们这个分类问题
我们都知道机器学习它分成两大类
第一大类是有监督学习
第二大类是无监督学习
对吧
有监督学习里面又分为什么
分类和回归
那所有的分类问题都要求什么
都要求我这个因变量必须为因子
当然在另外一些算法里面
比如说通过这个arules这个包里面的
apriori算法来挖掘关联规则的话
也要求什么
要求所有的参与挖掘的变量都为什么
都必须为因子
这就是在R语言里面为何要引入因子
这么一种数据对象
包括我们在后面的课程里面
在哪些具体的场景可能用到因子
我们简单做一个介绍
下面我们看看因子是如何创建的
要创建因子的话
我们有两种方式
第一种是基于一个向量
基于一个向量进行[创建]
比如说这里面已经是一个字符向量了
就是我总共有六个同学
把他们性别给记录一下
这个时候毫无疑问
我假如调用这个typeof()这个函数的话
它是一个字符
基于这么一种分类的字符
这么一个向量的话
我可以进行一个因子的创建
怎么创建
看一下 下面这条语句
factor
其实我们通过前面的向量的课程的讲解
包括我们现在在学这个因子的时候
都发现
在R语言里面
我们所有的数据对象
都是不需要进行事先声明的
我直接赋值就可以
而且具体的赋值时候
都是通过某个函数来创建它
前面这个向量的话一般通过什么
通过这个c() combine这个函数
然后对这个因子来讲
一般通过什么
通过factor()函数直接创建就可以了
我们看一下
一旦创建之后
我们再把这个性别
这个变量
我们敲出来之后一回车
这个时候它就有区别了
前面这个是性别本身
假如它作为一个字符向量的话
它是这么一个输出
然后假如是转化为因子之后
第一行还是一样的
我们看第一行还是一样
但是下面加了一个什么
加了一个levels
就是我的类别只有两种
一种男 一种女
我们一旦创建完这个因子之后
我们看看这个因子的一些最基本的操作
包括它的增加 修改 删除 查询 (增删改选)
假如要查询的话
和我们前面这个向量是一样的
也通过这个方括符来进行访问其中的子集
这里面当然既可以是这种一个1到n的正整数
比如说选择第一个
第四个第五个把这个元素给取出来
这是可以的
当然也可以通过什么
负号来反向选择
也可以通过类似于向量里面的什么
通过这个逻辑向量来访问也是可以的
同样 假如我们说要
改变其中某一个元素的话
怎么办
其实我就直接赋值
在R里面无论是对向量的增加
向量的修改
还是向量的删除
其实都是什么
都是赋值
比如说我现在要把第一个
这个性别的这个因子的第一个元素改成什么
改成男
完了我直接什么把男赋给他就可以
赋完之后我们再看看
性别是否等于毫无疑问这是一个什么
这是一个逻辑运算
就这长度为6的这个因子
我分别和这个男相比较
是不是等于男
是否为男性
这时候我们返回一个什么
长度为6的这个逻辑向量
关于这个赋值我们需要补充一点
咱们看一下
我们先看一下nlevels的时候
这个性别毫无疑问目前只有两种
一种是男一种女
我们可以通过这个levels()
这个函数直接将性别的具体的取值水平
也就所谓的类别显示出来
男和女
假如我现在要将什么
要将这个中性
当然我们这没有什么特别的含义
只是为了举这个例子而已
假如说中性也是一个可能的取值的话
那好
我将中性赋给这个第一个元素可不可以
这时候大家看一下
它出一个问题了
就出来一个警告
为什么
因为这个时候其实
我这个中性并不在这个水平里面
我事先定义这个因子的时候
它取得水平只有两种
一个男和一个女
那好
你后面要是将一个新的一个
不在男和女取值水平里面的一个
新的取值赋给它的时候
这个时候它是不允许的
它一旦这样创建的话
它会产生一个什么 缺失值
假如说我要将
这个中性硬要赋给它的话 怎么办
那这个时候我在定义的时候
就要增加一个参数了
比如说我这个性别
还是这个男男女女这么一个向量
对吧
一个字符向量
我还是通过这个factor()来创建一个因子
那好
创建的时候
即便我目前的取值里面
没有这个中性这个取值
那好
这个levels里面也是什么
也得指定 证明我既有男也有女
同时还有可能一个什么
取值水平是什么
是中性
假如一旦我们定义的时候
是加上了这个levels这个参数的话
那我们后面再重新赋值
毫无疑问就可以赋了
这就是我们在因子里面
进行操作的时候需要注意的一个点
就是在创建的时候有可能要用到什么
这个levels这么一个参数
我们再来看看关于这个因子的一个属性
我们在调用一下
前面我们将性别作为字符串对待的时候
毫无疑问这个typeof返回来的字符
那假如我现在变成因子之后
我们看一下
这个时候它返回的是什么
它并不是factor而是什么
注意了
这个时候它内部存储为什么
integer
表示什么意思
表示我内部实际上存储为
一个整型的向量
假如我现在调用这个as.numeric()
它出来结果是什么
2 1 1 2 1 2
当然我也可以把它转为字符
转为字符的话就是刚才看到的
女 男 男 女 男 女
其实我们一旦看了这个typeof
返回的结果是integer之后
我们就必须意识到这么一个问题
对因子来讲
我们可以把它分成两个层次来看
就实际上内存里面存的是什么
是我一个整型的一个什么
一个向量
然后我们表面上看的时候
平时我们使用的时候只会用上面这一层
就将它当成一个字符的向量来处理就可以
但是我们一定要注意
它实质上只是什么
只是一个整型向量而已
为了进一步说明这个问题
我们再看一个例子
我们现在创建
数值向量
通过一个c(10,20,20,20,10)
这么一个数值向量
我来创建因子
毫无疑问
我们可以调用什么
可以调用这个mean()
我求一下这个平均值
大家看看这个平均值结果是什么
这个结果是什么
是NA=Not Available
返回来一个缺失值
因为它什么
它是一个因子
它从表面上看它只是字符而已
所以直接用这个什么
用这个mean()这个函数
作用于它的话是没有效果的
所以只能什么
返回一个缺失值
那既然是说不能直接对这个因子求平均值
那我可不可以先转换成什么
先转换成数值可不可以
那好
我先 as.numeric()
这也可以
这个时候毫无疑问已经变成什么
已经变成这个数值了
但是这个数值我们返回结果是什么
很多同学可能期望
它应该是小于20大于10的一个数
但是实际上它的结果是什么
1.6
注意了 它的结果是1.6
这是为什么
我们看看这个
假如我们看一个代码比较复杂的时候
我怎么看
我就剥洋葱
洋葱从里面往外剥
把里面这个先拿出来看看
结果是什么
我们看看as.numeric()
这个函数返回结果是什么
1 2 2 2 1
大家注意了
当我即便是用这个数值向量进行因子创建的时候
其实这里面什么相当于是
"10" "20" "20" "20" "10"
先把它当成字符来对待了
所以实际上内部存储的并不是
10 20 20 20 10
而是什么
是1 2 2 2 1
无非它上面的标签是什么?
是"10"
加了一个双引号 表示它是字符
那假如我们想要得到结果
是16而不是1.6的话怎么办
我们这有两种方法
第一种方法
我先将什么
先将这个number_factors我先转换成
先转换成字符
这个时候相当于是
"10" "20" "20" "20" "10"
当然这个是加双引号的
加了双引号的字符
我再转换成as.numeric()
这个时候相当于变成
10 20 20 20 10
再来求这个平均值的话
毫无疑问它结果就16了
还有另外一种方法是什么
大家看这个
我先用这个levels(number_factors)
这个时候其实我得到结果是什么
c("10", "20")
当然这个是20是加双引号的
一个取值水平
取值水平那好
后面我用那个下标是什么
number_factors
其实就是1 2 2 2 1
然后相应地通过后面这一部分
它得到结果是什么
通过这个下标的操作
它得到结果其实就是
"10" "20" "20" "20" "10"
当然也是加双引号的
再作用于这个as.numeric()
毫无疑问把它变成这个数值型
最后再求这个平均值
得到结果同样也是 16
我们通过这么一个例子向大家展示了一下
对于因子而言
它表面上看是一个字符 一个字符向量
实质上在内存里面它只是一个整型的一个向量
这是关于因子的一些最基本的操作
当然我们前面讲这些因子其实都是什么
都是无序因子
就像我们说性别的时候
我们都说男女平等
所以说性别第一个取值xb[1]
大于性别的第二个元素的取值xb[2]
那毫无疑问这是没有意义的
那对于某些场合来讲
除了类别之外 除了定类之外
我要进一步做什么
进一步做定序
就它就是既有类别的划分
同时也有这个优劣有高下之分
那好 比如说成绩的话就有这么一个问题
我们将百分制成绩转换成五分制成绩之后
比如说有优 良 中 及格 不及格
那毫无疑问 优要比什么
要比良好
那这个时候我要创建因子的话
除了调用这个factors的这个函数之外
我还怎么样
一定得加上这个ordered
这么一个参数
它默认为FALSE默认的话
它是一个无序因子
创建的是无序因子
假如我要创建有序因子的话
必须加上什么
将它这个参数设置为什么
TRUE
这个时候我们一旦是做了
这个有序因子的设定之后
创建score这个有序因子
那好我们再看一下
第一个元素是不是大于第二个元素
或者是优是否好于这个良
这个返回结果就有意义了
它的返回结果就是什么
就是一个TRUE
这个时候可能有同学会有疑问了
为什么说这个R怎么这么智能
它自动就识别出来
优比良好 良比中好
为了说明这个例子
我们再看另外一个
比如说我现在有周一 周二 周三 周四
类似这样的
这么一个关于星期几的字符
我基于这个字符向量
我也创建个什么一个有序因子
同样也是用factor这个函数
我们先看一下
这个有序因子第三个元素
是否是小于第二个元素的
也就说周二是不是在周三前面
周二小于周三
它返回结果是什么
TRUE 是真
这个果然又是非常智能的
我们再看
第一个元素和第二个因素相比
周一和周三相比
我们期望的毫无疑问什么
周一应该是小于周三的
周一小于周二再小周三
这是我们的一个常识
但实际上结果是什么 FALSE
为什么
我们可以把这个days这个有些因子敲出来
一回车 看一看它的实际结果是什么
你发现它结果是什么
注意了
这个levels里面是什么
周二 < 周三 < 周一
为什么
其实R里面并没有这么智能的一个识别的机制
它是没有的
完全没有
它为什么有这样的一个顺序
它其实道理也非常简单
这里面就是一个内部编码的问题
哪个编码小那就得放在前面
哪个编码大的话就放在后面
这里面其实我们也不用记它
我们只要看什么看这个拼音就可以
假如是26个字母的话
就ABCD一直往这样
这样按这个正常顺序走就可以
假如是我们那个中文的话就看什么
看拼音
比如说周二 周三 周一
那毫无疑问什么
周二Er
周三San
周一Yi
毫无疑问应该是这么一个顺序
所以这时候我们也理解了
为什么周二摆在周三前面
周三又摆在周一前面
这里面都是一个所谓的拼音的顺序
那假如我要按这个符合常识的话
将周一放在周二前面
然后周二放在周三前面
这时候怎么办
这个时候我们在创建这个因子的时候
又要重新设定什么
设定levels这个参数了
大家看一下
还是前面的函数前面
这一部分是完全一样的
就是基于这么一个字符向量
我来创建一个有序因子
但是要设定levels
是周一 周二 再周三
当我们一旦设定之后
我们就可以看这个days的话
毫无疑问是它的水平
毫无疑问是它的水平
什么周一小于周二小于周三的
后面这两个判断语句也是符合我们的常识的
我们前面通过几个简单的例子
看了一下如何通过向量来创建因子
包括这个无序因子和有序因子
接下来我们讲一下第二种
R里面第二种创建这个因子的方法是什么
就通过这个已有的一个数值变量
我进行分箱
进行离散化处理
它也得到一个什么
也得到一个因子
我们看一下
并且一个实际的场景来看看
比如说我们现在有这么一个场景
就什么
就是我有一个向量
用来存储什么
语文成绩
毫无疑问
这个语文成绩什么是一个数值向量
这个时候我想将这个百分制的成绩变成五分制的成绩
那毫无疑问
要由这个0到100
任何一个数字都是有可能的
取值我要变成什么
优 良 中 及格 不及格
变这么五个区间
这时候怎么做呢
这个时候我通过什么调用
这么一个函数叫cut
这个cut我们其实可以很直观的看出来它是什么
把它切分
当然这个切分并不是说
像我们这个拉面师傅的切面条一样
不是那样的
更准确来讲
它应该属于一个“挖坑”的过程
什么意思
我们看这个cut函数里面包含两个参数
第一个什么
就是被cut的对象
就我们前面这个已经定义好的数值向量
另外还有一个什么
breaks
这个相当于是挖坑的时候
它几个端点
我们看一下 0
后面是什么
6到10就是6 7 8 9 10
然后乘了10就变成了60 70 80 90 100
总共加起来什么
总共有这个六个端点
六个端点分成了五份
分别是
0
60
70
80
90
100对吧
这个相当于已经挖了什么
挖了五个坑了
那原来的数据相当什么
原来比如说
94 87 92 91 85 92
那分别什么
比如92跳到哪
跳到这个坑里面来了
然后85条这个坑里面对吧
依此类推
就这么一个所谓的将原始的数据
cut了之后
其实相当于什么
给它装到不同的箱子里面去了
我们看一下具体结果
这个时候一旦你cut完之后就变成什么
变成一个五分制的成绩了
cut完的结果是什么
是(90,100] (80,90]
(90,100] (90,100]
(80,90] (90,100]
毫无疑问就是分别是原始这个数值
它相当于这个数据的粒度变得更加粗了
然后它分别变成区间
用这个区间来代替原始的数值
我们粗略的看的话
仿佛这个百分制已经顺利的变成了五分制了
但这里面有几个问题
我们先看一下
看一下这个levels
毫无疑问这里面
其实并没有取到0到100的所有的数据
有一个取值是没有取到的 是多少呢
我们看所有的区间都什么
左开右闭
那毫无疑问这个0是没有取到的
0是没有取到的
那这个时候怎么办
我需要加一个参数
要将这个最小那个值也保留到
就是因include.lowest
表示什么
表示最小那个区间里面
是左边也是闭 右边也是闭
两边都是闭区间
毫无疑问
这个时候什么
这个时候所有的取值0到100都是取到的
我们刚才经过加这个
include.lowest的这个参数之后
发现这个已经改好了
就是已经把最小这个值已经包含进来了
也就是说0到100
所有的取值都能取到
但这个时候其实还是有问题的
比如我们现在将百分制变成五分制的话
60分的话毫无疑问什么应该属于及格
但是在我们这个目前这个levels里面有一个问题
它是[0,60]
因为所有的区间都是什么
左开右闭
那这里面这个60分归为不及格
毫无疑问 这是有问题的
这个时候我们需要进一步设置参数
设成什么
加一个right=TRUE参数指定了
毫无疑问
我们看看这个结果就变成什么
左闭右开了
这个时候每个取值
其实就和我们想要的这个
[60, 70) [70, 80)
都是左闭右开这么一个区间
这么一个取值区间应该就没问题了
是一致的
当然这个时候我们看这个levels
的时候发现所有的取值区间都是什么
都是并行的
并没有高下优劣之分
也就什么意思
并不表示这个取值区间比这个取值区间好
那所以我们进一步还需要设置参数
是什么
要将这个无序因子变成有序因子
将我这个结果order了一下
然后我们再看levels
毫无疑问
它已经变成那个有序的了
当然我们在将百分制变成五分制的时候
最好除了这个区间划分之外
我还最好加上一个什么
加上一个标签
就比如说这个[90, 100]
我就加上标签是优
[80, 90)就是良
那进一步贴标签那怎么贴
我要加一个什么
加个labels
大家注意了
这个labels的话
你必须和什么和前面那个区间要一一对应
也就是因为区间是从小到大进行排序的
就从这个breaks进行排序的话
那毫无疑问这里就变成不及格 及格 中 良 优
千万不能倒过来
倒过来的话 那不及格反倒变成优了
经过这一系列的这个参数的设置
最后得到结果
levels是不及格 及格 中 良 优
同时这个取值也贴上了标签
就顺利地将我们这个百分制成绩变成了五分制的成绩
以上我们通过一些简单的例子
看了一下在R里面两种最基本创建因子的方法
第一种是基于这个类别的向量
我通过factor函数直接创建一个因子
无论是有序的还是无序的
另外一种方法是什么
通过这个cut()这个函数
将已有的一个数值向量
将它离散化变成一个因子
这两种因子(创建方法)在我们后面的课程里面也会经常用它
本次课到此结束
谢谢大家
-第1章 气象万千、数以等观
--第1章 作业
-第2章 所谓学习、归类而已
--第2章 作业
-第3章 格言联璧话学习
--第3章 作业
-第4章 源于数学、归于工程
--第4章 作业
-讨论题
-第5章 工欲善其事、必先利其器
--第5章 作业
-第6章 基础编程——用别人的包和函数讲述自己的故事
--6.1 编程环境
--6.4 控制流
--第6章 作业
-第7章 数据对象——面向数据对象学习R语言
--第7章 作业
-第8章 人人都爱tidyverse
--第8章 作业
-第9章 最美不过数据框
--第9章 作业
-第10章 观数以形
--第10章 作业
-第11章 相随相伴、谓之关联
--11.1 导引
--第11章 作业
-第12章 既是世间法、自当有分别
--12.1 导引
--第12章 作业
-第13章 方以类聚、物以群分
--13.1 导引
--第13章 作业
-第14章 庐山烟雨浙江潮
--第14章 作业