dplyr是由Hadley Wickham主持开发和维护的一个主要针对数据框快速计算、整合的函数包,同时提供一些常用函数的高速写法以及几个开源数据库的连接。此包是plyr包的深化功能包,其名字中的字母“d”即来源于data frame,以示其专注于数据框数据的整理和操作。我们将在本章中着重介绍一些数据处理方面的常用功能函数。
1.1管道函数
在前面的简介中,我们计算了cran上的可用的函数包的数量:
> contrib.url("http://mirrors.xmu.edu.cn/CRAN","source")%>%available.packages%>%nrow
[1] 6450
在以上的代码中,我们使用了“%>%”这个符号(或者说函数),这可以被称为管道函数。管道函数在其他的语言(比如shell)中也经常被使用,而其他的函数包中也有类似的功能函数(pipeR包和magrittr包),我们稍后也会对magrittr包中管道函数做介绍。
“%>%”这个管道函数把左件的值发送给右件的表达式,并作为右件表达式函数的第一个参数。
左件%>%右件
通常来说,可以把“%>%”读作then,即然后。
如果你需要同时操作多个数据集或者多个函数时,使用管道函数将会更加方便、快速和有逻辑性。比如以上的计算函数包数量的代码若改为一般写法:
nrow(available.packages(contrib.url("http://mirrors.xmu.edu.cn/CRAN","source")))
或者是这样:
x=contrib.url("http://mirrors.xmu.edu.cn/CRAN","source")
x= available.packages (x)
nrow(x)
对比这三段代码,第二段代码包含了3对括号,可读性比较差;第三段代码将之分为三句,代码量增加,并且留下了x这个中间产物;而第一段代码乍一看很长,但实际上对于代码的运行、传递机制表现得很清晰,各阶段的函数分工明确,逻辑清楚,如果习惯使用后,可用性相当好。
值得一提的是,管道函数还可以用在自定义函数(function)中,比如我们定义一个对向量中的数求整后取绝对值求和的函数。
一般代码:
> f1=function(x)sum(abs(round(x)))
管道函数代码
> f2=.%>%round%>abs%>%sum
我们来看看源码的显示:
> f1
function(x)sum(abs(round(x)))
> f2
Functional sequence with the following components:
1. round(.)
2. abs(.)
3. sum(.)
Use 'functions' to extract the individual functions.
毫无疑问的是,两者并没有什么不同,来看下面的结果。
> set.seed(1000)
> a=rnorm(20,10,10)
> a%>f1
[1] 161
> a%>f2
[1] 161
当然,R中并不仅仅只有这一个管道函数,同样由Hadley Wickham开发的magrittr包中介绍了其他功能的管道函数。
函数名 功能
%<>% 在%>%的基础上,会把右件的最终返回值返回给左件(注意是最终)。
%T>% 把左件的值传入后,不产生任何返回值(你可以对计算的中间过程画个图,再接着计算)。
%$% 选取左件中的任意个变量名来操作,但左件中原来的数据将不会被保存,仅剩下计算后的值。
> test=data.frame(x=a,y=sample(0:1,20,replace=T))%T>%
+ plot%$%
+ f2(x)
> test%<>%"*"(10)
以上代码简单地运用了上述3个管道函数,第一行先构建一个数据框对数据框画散点图并对x变量运算赋值给test,第二行对test乘以10倍。
管道函数是一个非常方便快捷的工具,在本书后续的其他程序里,我们将大量地使用管道函数,以增加代码的可读性,减少代码量。
1.2基础函数
在数据分析中,我们往往受限于分析目标和具体实现两个瓶颈。在日常交流中,数据分析师们也经常表示自己大概会分配70%-80%的项目时间用于数据处理,毫无疑问,Hadley Wickham所开发的一系列函数包也都围绕着如何减少数据处理时间这个目标来进行。能够快捷方便地表达并实现自己心中的目标,才有更多的时间用于思考和分析。
dplyr包的函数能处理很大一部分结构化数据处理场景中所需的功能,筛选、排序、变量选择、变形、汇总等。
1.2.1 filter筛选
filter按照筛选条件或逻辑筛选出符合目标的子集,与base中的subset十分相似,不过跟其他dplyr包中的基础函数一样,filter中可以直接调用数据框中的变量名,而无需attach或者使用”$”。
举个栗子:iris数据集中Species不等于setosa和virginica,且Sepal.Width大于等于3.2.
> iris%>%filter(!Species%in%c("setosa","virginica"),Sepal.Width>=3.2)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 7.0 3.2 4.7 1.4 versicolor
2 6.4 3.2 4.5 1.5 versicolor
3 6.3 3.3 4.7 1.6 versicolor
4 5.9 3.2 4.8 1.8 versicolor
5 6.0 3.4 4.5 1.6 versicolor
1.2.2 arrange排序
arrange可以根据变量名依次对数据框进行排序,靠前的变量优先级越高,对变量名使用desc函数即为倒序。plyr(我们以后会介绍的一个包,同样出品自Hadley Wickham)中也有一个相同的此函数。