当前课程知识点:R语言数据分析 > 中部:执具 > 第8章 人人都爱tidyverse > 第8章 人人都爱tidyverse
欢迎大家来到《R语言数据分析》课程
咱们今天要交流一个非常有意思的主题
叫人人都爱tidyverse
咱们伟大的托尔斯泰曾经说过一句话
幸福的家庭都是一样的
不幸的家庭各有各的不幸 对吧
哈德利他也说过一个类似的话
整洁的数据都是比较相似的
这个混乱的数据
它各有各的混乱的形式
也就是他有这么一个理念之后
他就自己哈德利Hadley就专门倡导了一种
编程的一种 风格一种理念
也就提出了一个这么tidyverse一个工具包
这么一个扩展包的套装
我叫它扩展包套装(或者说全家桶)
咱们先看看这个名称
tidy
verse
tidy毫无疑问它是整洁的 整齐的 平整的
平平整整
这个verse
假如作为名词的话
它表示诗
韵文
诗篇 对不对
当然它也可以作为一个后缀
比如说universe
inverse
表示一种转变
所以其实我们把这两个字放在一起的话
其实就相当于什么
我们在创造一种新的一种编程的理念
一种新的编程的风格
这种风格最早可能叫
Hadleyverse
Hadleyverse
也在这个名字后面加了这么一个后缀
后来是取名叫做tidyverse
我们看了这个名字之后是比较兴奋的
确实他在倡导一种新的编程理念
让我们的代码更加优美
甚至像诗篇一样优美
那我们看看它究竟是一个什么样的
工具包 扩展包的套装
我们通过library这个函数
加载了tidyverse之后
你会发现
它其实加载的不再是单个的包了
而是多少啊 1-2-3-4
5-6-7-8
总共8个包
每个包是什么功能
咱们看一下
ggplot2
这是大名鼎鼎的ggplot2
它是基本上是颠覆了整个R语言绘图系统
一种全新的风格现在用得非常非常多
dplyr这个包主要是用来做数据的处理的
tidyr它主要用来做对data tidying
其实在很多的数据处理里面
比如说数据的长宽变换
都是通过这个包实现
readr表示什么呢
数据的读入
数据的导入
后面的一些包比如说
purrr
做一些函数式的编程
tibble
它其实本质上是
我们可以把它当成一个
更高版本的data.frame
还有后面这两个包分别是针对字符串
以及针对这个我们的因子
也就是所谓的类别变量
类别变量的两个包
这些包其实他们功能非常的丰富
功能非常强大
咱们今天重点讲一下这个包
dplyr
像其他一些包比如ggplot2
我们后面在后续的章节里面
观数以形
就是如何做探索性数据分析的时候
我们会再展开讲
咱们今天先把这个包讲一下
当然在讲这个包的过程中也会涉及到其他一些
包里面的一些相应的函数
在讲具体的如何做数据处理之前
我想先把这个符号给大家引荐一下
这个符号是什么呢
管道操作符
它其实非常简单
就是两个百分号
括起来一个什么呢 一个大于号
但也非常形象是向前向前向前
就这么一个非常形象的一个符号
它是用来实现什么功能的呢
它其实是一个二元操作符
我们前面讲了
其实这种百分号括起来都是二元操作符
所谓二元操作符就包含两个部分
左半部分 右半部分
这个rhs表示什么呢
Right-Hand-Side
表示右手这一侧
它其实接受两个参数
相当于左侧这个是一个值value
右侧是一个函数
所以
它这个最基本的一个形式
比如说x
我们这个管道操作符
再f
表示什么呢
表示f(x)
它其实是简写的一种方式
当然这里面相当于是什么呢
只有x这么一个参数的时候可以这样写
f这个函数只有x这么一个参数的时候这样写
假如它有多个参数
并且这个比如说有两个以上
两个以上的参数的时候
并且x是是第一个参数
这个时候
按下面这种方式来写它
当然也有可能说
我有多个参数
但x呢
但前面这个值它不是
但前面这个值它不是第一个参数
这个时候我用点号来代替它
大家注一下这个点号
我们后面会多次用到它
就是用来指代前面这个value
当然我们刚刚讲了
这个管道操作符
像管道一样
一步一步一步一步
不断的递进
对于某一个数据来讲
我做了一系列的操作
前一个操作是后一个操作的基础
也就是说后一个操作基于前一个操作的结果
这种操作其实在我们R里面
在做数据分析的时候会经常用到
比如说我拿到一个数据框之后
我可能说做什么呢
我先要选取其中的一些列
然后
这是第一个动作
然后我要对这个列做一些变换
这是第二个动作
然后变换完之后我再绘制图形
第三个动作这个时候用到
第一次操作 第二次操作 第三次操作
本质上有这么一个过程
但是当我们有了这个管道操作符之后
整个代码会非常的简洁
这也为什么说它属于tidyverse
这么一个扩展包的套装
我们前面讲了一下这个基本的理念
我们来看看具体实现
比如说我有成绩表cjb这个数据
我现在想对成绩表的前6行进行查看
怎么办
毫无疑问
我们用的还是个head这个函数
但是我用了另外一种写法
用的是管道操作符
然后得到结果是什么呢
跟我们前面的结果是一样的
但是它写起来非常简洁
cjb %>% head
假如我这边有多个参数
比如说我们现在不想显示默认的6行
而是指定只选择4行
这也就有两个参数了
这个时候还是成绩表还是放前面这个value
就这个值还是放前面
然后这个函数还是放后面
但是我可以指定其他的一些参数
这个时候上面这个语句和下面这条语句
其实是完全等价的
只是它倡导的是一种新的风格
当然这个比较简单的操作里面
还没有充分的显现这个管道操作符的优势
我们只是给大家展示一下它是如何来使用的
我们在看后面一些相对比较复杂的操作的时候
我们慢慢就能体会到管道操作符
确实让我们代码更加优雅
我们来看一看具体的我们要讲这个dplyr
这个包里面的一些函数
这个包里面当然函数非常多
但我们这个时间有限
我们只挑出其中几个用得比较多的函数
第一个函数select()
也就是选择某些列
第二个函数mutate()
就是对某些列进行修改
增加或者修改
第三个是针对行的
前两个针对列的
第三个针对行的filter()
过滤
当然这不是
滤波器之类的这
这是过滤
我就选择符合条件的某一些行
某些记录
后面这个一看这个函数名称就知道了
它是用来做排序用的
最后还要讲一个summarise()
表示汇总
一般我们用的时候
要和这个group()
group_by这个函数联合使用
用来分组进行统计
我们下面看看这些具体这个函数
是怎么
具体的功能
具体的使用
比如说我现在cjb总共有十几列
我先不想看那么多列了
我只想找其中的xm yw sx这三列
然后我把这个三列拿出来之后
我看一看这三列的情况
只看其中的前三行
那我用了两个管道操作符
成绩表我先选择这三列
然后
我把选择到了这三列的结果
再交给这个head
这时候就是什么
就是连续的操作了
所谓像管道化的连续操作
得到结果是我们下面这个结果
这么一个tibble
它其实你可以把它理解为data.frame
一个升级版
当然这个结果可能不是特别满意
这里面比如说你显示的时候
xm yw
sx表示数学
还不是特别明显
当然我们在编R的代码的时候
我们这么一个主张
就是在无论是变量的名 命名也好
还是我们某一列命名也好
最好不要用中文
但我们到最后显示结果的时候
毫无疑问我们最好是希望看到中文
看到具体的更加直接一点的中文
那这个时候我可以把
进一步
增加一个管道的操作
看看把这个xm yw sx再把它变成中文的
我们看看怎么实现
这个时候其实只要加一个函数叫set_names()就可以
你前面这一部分不是已经选择了
这个775行数据里面的三列了
选择完之后怎么样
我把这三列的名称改成姓名语文数学
然后再取其中的前三行
一看结果变了
姓名语文数学已经出来了
咱们再看一看
我现在选择的是第1列
第4到12列
我可以通过
也可以通过我们的下标
一个正整数来选择它
就是第1列和第4到12列
也就是什么
姓名之外 所有九门课的成绩
同样我们也是不显示所有的数据
只显示前三行
这得到一个结果是一个3乘10的一个tibble
当然我们这稍微展开一下这个tibble这一块
比如说第一个姓名它是字符型
后面的dbl表示dbl=double
它是一个双精度型的一个数值型的
再比如后面这个
假如我现在不用什么呢 我用的不是这个正整数
而是xm
yw:sw
表示什么呢
因为我们第1列的名称是姓名xm
然后第4到第12列分别是
yw sx一直到sw
大家注意了
这个时候假如我想连续选择某些列的时候
只要把这个列名中间加一个冒号就可以
这也是tidyverse这个扩展包里面
给我们提供一个非常大的便利
所以这个结果
和我们前面那个代码的结果是一样的
只不过我们不再需要记住它究竟是第几列了
而是直接把这个列名放进去也可以
前面是列的选取
我们再看一下这个mutate列的修改
我们前面在讲这个bj xb wlfk的时候
这个数据一旦读进来之后
它首先默认是是一个字符向量
我们得把它变成因子
一种写法是复制粘贴
先写一个bj
转换成这个factor一个代码 bj <- as.factor(bj)
然后把后面这个复制一下
xb和wlfk也套用同样的修改方法
但是我们在这个tidyverse这个扩展包里面
直接可以按这种方式写mutate_at
bj xb wlfk
我都做一个factor这么一个转换
转换成因子了
非常简洁明了
而且我们后面代码是非常容易维护的
再比如说我想增加一列总成绩
zcj 怎么增加
我用这个函数
因为总成绩相当于是第4到第12列的
这每一列要求和对不对
它每一列相应的行求和就可以
所以是rowSums
这个时候首先对bj xb wlfk进行了一个
因子类型的转换
同时增加了一列叫zcj
这已经做两个操作了
已经有两个管道操作符
第三个操作是什么呢
我再按总成绩进行排序
是从高到低从低到高排序
一看 desc叫从高到低排序
默认的一般都是从低到高
然后假如我想从高到低 降序排列的话
就用这个函数desc()
我们看看排在最后的两个同学是谁
就是tail和刚才那个head是相对应的
一个是前面的若干行
一个是后面的若干行
这时候我们求的是最后两行
发现在全年级775个同学里面排最后的分别是谁
一个叫滑亚 一个叫张良平
最后这个同学所有分都为0分
他可能是因为原因可能没有参加考试
或者其他一些原因
总成绩垫底
前面就是我们讲到这个是管道操作符
不断的进行操作
后续的环节基于前续的环节
但是我们需要注意的是在这个操作完之后
它会直接显示出来
但同学们有没有注意到
这时候成绩表本身
有没有做改变
没有
整个这段代码其实生成的是一个
是一个临时的一个数据对象
成绩表本身假如你现在重新把这个成绩表
View一下的话显示出来
你发现它还是原来的那个成绩表
并没有做这么多的操作
也没有增加总成绩这一[列]
也没有按它的进行从高到低进行排序
假如我需要对这个成绩表本身进行修改的话
比如说我要对它进行因子类型的转换
同时要增加这一列的话怎么做
应该用到下面这一个操作符
就是百分号里面括起什么
既有向前的大于号
也就说向前操作完之后
我还得回传加这么一个小于号
表示回传给cjb
当然这个符号其实和下面这个代码
它的结果是完全等价的
也就说我后面得到一个结果
进行了那个相应的列的修改
同时进行了排序
然后我把这个结果重新赋给cjb
这也实现了我这个整个这个修改
就直接把这个cjb这个数据本身进行修改了
而不是一个临时的数据对象
以上就是我们讲的关于这个列的一些操作
我们再来看关于行的一些操作
要选择某些行的话
比如说我现在找一下
有哪些同学的语文成绩是不及格的
小于60分
怎么写呢就是filter
表示过滤一下
把这个符合后面这个条件
所有的记录显示出来
一看有这么几个同学
也就是这个刚才看到这个
滑亚和张良平这两个同学
只有这两个同学语文成绩不及格
那我们可以再进一步扩充一下
比如说我想知道
哪些同学有某门课不及格
而不是说语文或者数学具体某一门
而是说这个九门课里面只要有一门不及格的
我就把这个同学给挑出来
那这个怎么实现
我是不是说我要写连续后面写yw < 60
sx < 60, ...等等那太复杂了
一个比较简洁的方法
大家看一下就是filter_at
也就说针对第4到第12列
也就是我们这九门课的成绩
是不是存在某一列符合什么条件
它小于60分
这个时候又用到这个点号了
也是指的我们具体的这个数据
这个时候我们通过这么一个简单的一个写法
毫无疑问就把只要这个同学
他有某一门课是不及格的
我就把它列出来了
总额多少同学呢52个同学
存在不及格的现象
所以总整体来讲
775个同学他成绩还是比较好的
这就是我们那个dplyr里面
对行和列的一些最基本的操作
咱们再给大家介绍一个非常有用的
也是后面在数据分析里面经常用到的一个功能
叫分组统计
分组统计什么意思呢 大家看一下
比如说我们现在有两列我们关注一下
一个是xb这一列
一个是zcj这一列
那我现在可不可以这样做一个统计
就是对于总成绩来讲
我想知道男生和女生有没有区别
比如说这男生
我们是不是可以作为一组
然后女生作为另外一组
它相应的总成绩
比如说它的平均分
它最高分最低分是不是有区别
这个时候其实相当于两组
这两组的话就是相当于这里面的两列相呼应的
一个是做来分组的 xb是分组变量
然后这些统计的对象是谁是zcj这一列
假如要做这种分组统计的话
用到我们刚才讲到的summarise这个函数
用这个函数来做统计
统计汇总
但是我要基于哪个分组基于xb进行group
进行分组
比如说我对每一组它究竟有多少个同学
我统计一下它最高分统计一下
平均分 最低分统计一下
也就是我们刚才看到的
对这里面总成绩
它把那个人数求出来
男生里面有多少个男生
然后女生里面总共有多少同学
然后他最高分最低分他的平均分
这里边简单的几行代码
就把我们整个这个700多个同学
进行了一个分组的统计
所以它代码也是非常容易理解
非常简洁明了
这种分组的方法比较容易理解
也就说有一个分组变量
有一个我们的目标变量
那我们再看另外一种需要分组的情况
假如我们要实现对这个
语文数学外语政治这九门课
也做一个(每门课的)分组统计
针对性别一样
对它的那个总成绩进行分组统计的话
那这个时候我们要做一个数据的长宽变换
咱们看一下具体是如何实现的
所谓数据长宽变换
我们先有个概念
我们那个数据可以分为宽的数据和长的数据
宽的数据什么意思
它本身列表比较多
所以它比较宽
那所谓长的数据是什么
行比较多
我们要做这个数据长宽变换的话
它要使用到我们刚才讲到的
这个tidyr这么一个包
其中有两个函数
一个是gather
一个spread
这两个
咱们看一看这个长宽变换的过程
比如说我们现在有
xm xb yw sx wy
有这么几列
现在我想把这个yw sx wy
我要做分组统计的话怎么办
我得把它进行把宽的数据变成长的数据
我们看一下
先看看这个长宽变化之后的结果
这里面其实是有原来是有三列
现在我们其实变成了两列
所谓宽的数据变成长的数据
就是由原来的若干列变成两列
什么意思呢
原来的比如说yw sx wy有三列
现在其实只变成两列了
一列是我这里面原来的变量名
另外一列是这个变量的取值
我们看一下
比如说汤海明男
他以语文是87 数学94 外语89
汤海明
他语文是87数学94外语89
所以我们看得出来
宽的数据变成长了数据之后
它其实只是形式上变了
它的信息量完全没有变化
就内容是完全一样的
这里边就是所谓的数据由宽数据变成长数据
就是说由原来的若干列变成现在的两列
原来的变量名放在第一列里面
原来的变量的取值放在第二个列里面
当然我们这个数据由宽变成长
这种这种变换方法并不仅限于三列数据
你无论多少列数据都是
都是由若干列变成两列的过程
相反
假如我这个数据由长数据变成宽的数据的话
那就是一个反变换的过程
这里面相当于什么 就是spread
其实这两个词也非常形象
所谓gather什么意思
我就把这个数据
它特别长(口误:宽)的数据我搂过来
捞到怀里来
那慢慢的变长了
就由原来的多列变成现在的两列
由原来的一行变成现在的多行
原来假如是有一行
它原来有有三列的话
那好现在就得变成三行了
假如原来有九列
它原来一行就变成
现在多少
变成了现在的九行
spread相当于什么意思
我把它伸展开来
相当于是把这个长的数据又反过来变化成
宽的数据
这就是我们所谓的数据的长宽变换
咱们来看一看
假如一旦这个数据做长宽还变换之后
它自然就可以像我们那个性别一样
进行分组统计了
比如我们看一下
我们对刚才这个yw sx wy这三门课的成绩
我们做了长宽变换
由原来的一行变成三行
这个时候比如汤海明语文数学外语
舒江辉语文数学外语等等等等
我们再按照key这一块再做一个排序
我们把语文成绩都排一起
把数学排一起
把外语排一起
这个时候毫无疑问
我这个Key这一列可以作为我的分组变量
然后这个具体的取值
它的成绩可以作为我的目标变量
我要统计这个变量
一旦做了这个转换之后
毫无疑问就可以套用前面我们
就像我们根据这个性别来做
相应的分组统计一样
我现在可以根据科目来进行分组统计了
我们来看一下具体代码实现
对cjb这个数据
我还是调用gather这个函数
那这个key我重命名一下叫ke_mu
然后这个value我重命名一下叫cheng_ji
那究竟把哪些列由宽变成长
把它搂到这个怀里来
就是语文一直到生物这九门课的成绩
毫无疑问这个总共是九列
也就是原来的每一行应该要变成现在多少行
九行
我们看看具体结果
具体结果多少
大家看一下
6975乘以7
不再是775了
为什么呢?大家看一下
因为你一行变成了多少变成了九行
所以它总的行数多少
775乘以9
毫无疑问就是多少6975
所以就达到了刚才的效果
我们再看一下具体的结果
这里面其实我们关注的是这两个
一个是科目
一个是成绩
我们要根据ke_mu进行分组
然后对cheng_ji进行统计
那这里面有语文成绩数学成绩外语成绩等等
具体统计的话
我们再往后面再加管道符
再来做进一步的操作
也就说在前面这个gather的基础之上
我要做group
按照科目进行分组
然后再summarise
统计哪些量它的最大值
这每门课最高分
每门课的平均分
每门课的中位数
每门课的最小成绩
并且最后这个统计结果
我按照平均分从高到低进行排序
从高到低进行排序
所以这里面可以看一下
大家可以体会一下这个管道的操作的过程
我对成绩表这份原始数据
775乘以13的原始数据
我先过滤掉总成绩为0的分
因为它们是没有意义的
这个时候把这个分
因为他可能是因为某些原因可能缺考等等
他做统计的话没有意义
所以我先把这个过滤掉了
然后做数据长宽变换
再做分组
然后再做summarise
再做汇总统计
最后将汇总统计结果做一个排序
所以它其实有好多连续的操作
以一个管道的方式写的话
这个代码就相对比较简洁了
具体结果我们看一下
我们可以看出来
我这个平均分从高到底排序的话是多少
是地理 > 政治 > 化学 > 历史
外语 > 语文 > 生物 > 数学 > 物理
当然同学们可能也会注意到
一个比较有趣的现象是什么
平均分地理政治化学等等是比较高的
然后数学物理是比较低的
但是sd就是我们标准差
也就是反映我这个同学们某门课的
它的那个离散的程度
你发现这个平均分越低
然后离散程度相对是越高的
这其实也是我们后面需要进一步探索的地方
以上我们也对tidyverse这个扩展包的套装
进行了一个简要的讲解
当然这个包的内容非常丰富
功能也非常强大
我们这边只是抛砖引玉
让大家对这个tidyverse
这么一种编码风格有所体会
也希望大家进一步花更多的时间去探索它
本次课到此结束
谢谢大家
-第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章 作业