专栏名称: 表哥有话讲
国内最大的R语言专业学习平台| R官方认证学习实践社区--校企实践交流、名企内推和成果分享,立即关注-掌握R语言全球最新资讯与成果!
目录
相关文章推荐
51好读  ›  专栏  ›  表哥有话讲

R语言向量化运算:apply函数族用法心得

表哥有话讲  · 公众号  ·  · 2017-11-07 11:58

正文


作者: 鲁伟 ,热爱数据,坚信数据技术和代码改变世界。R语言和Python的忠实拥趸,为成为一名未来的数据科学家而奋斗终生。个人公众号:数据科学家养成记 (微信ID:louwill12)


当初入坑R语言的时候,就在各种场合看到老司机的忠告,“尽量避免使用循环!”一开始并不明白这其中的奥义,直到后来对R语言有深入接触后,才领会R语言在向量化运算方面的强大功能。本篇内容就总结小编在使用R语言向量化运算apply函数族的一些心得体会。


至于R写循环为什么执行效率低下,小编也从技术论坛上得到了一些解释。说是像for和while之类的循环语句是基于R本身来实现的,而apply函数族的向量化运算是基于C语言函数来实现的,所以二者的计算效率有很大差距。小编不是计算机出身,也不懂C,既然大神们这么说了就知道是这么回事就好啦。


所谓apply函数族,指的是以apply函数为核心,包括lapply, sapply, tapply, mapply, rapply, vapply, eapply等在内八个函数。先上个表格具体理解下每个函数的含义:


函数名

含义

apply

apply

lapply

list apply

sapply

simplify list apply

tapply

table apply

mapply

mutiple list apply

rapply

recursively apply

vapply

vector apply

eapply

environment apply


再上个图看一下apply函数族各函数之间的关系:

(图片来自张丹老师博客http://blog.fens.me/r-apply/)


apply函数

作为该函数族最原始最核心的函数,apply函数一直担任着向量化运算的艰巨任务。apply函数可以对矩阵和数组以及数据框按照指定的函数在不同维度上进行循环运算,其用法如下:

apply(X,margin,FUN,...)

X:矩阵,数组,数据框

margin:对象维度,表示按行还是按列,1表示行2表示列

FUN:对X执行运算的函数

具体用法可看实例:

x dimnames(x)[[1]] (x1x1 x2
3 3

(col.sums x1 x2
24 24

(row.sums a b c d e f g h
7 6 5 4 5 6 7 8

rbind(cbind(x, Rtot = row.sums),
Ctot = c(col.sums, sum(col.sums)))
 x1 x2 Rtot
a  3 4 7
b  3 3 6
c  3 2 5
d  3 1 4
e  3 2 5
f  3 3 6
g  3 4 7
h  3 5 8
Ctot 24 24 48

tapply函数

tapply函数应用于分组循环计算,其功能类似于dplyr包中的group by函数。其用法如下:

tapply(X,INDEX,FUN,...,simplify=TRUE)

X:向量

INDEX:用于分组的索引

FUN:应用于X的函数

. . .:接收多个数据

simplify:返回值是否数组化

用法实例:对iris数据集中按花种类计算花瓣宽度的均值

attach(iris)
tapply(Petal.Width,Species,mean)
setosa versicolor virginica
0.246  1.326  2.026

lapply和sapply函数

这两个函数放一起讲,那当然是它们实在太相似了。lapply函数顾名思义,list apply,除了其对象参数是一个list或者data.frame之外,其返回值也是一个list。而sapply函数作为一个简化版的lapply,其返回值形式可以不是list。二者用法如下:

lapply(X,FUN,...)
sapply(X,FUN,...,simplify=TRUE,USE.NAMES=TRUE)

X:矩阵,数组,数据框

FUN:作用在对象上的函数

. . .:其他参数(可选)

simplify:是否数组化

USE.NAMES:若X为一个字符串,TRUE表示设置字符串为数据名

用法实例:

elapply(e, fivenum)  
$alpha
[1] 3 4 5 6 7

$beta
[1]    7.389056   37.341843  148.413159  750.030976 2980.957987

$gamma
[1] 0.0 0.0 0.5 1.0 1.0

#simplify参数为FALSE时,sapply与lapply效果一样
sapply(e, fivenum,simplify=FALSE)
$alpha
[1] 3 4 5 6 7

$beta
[1]    7.389056   37.341843  148.413159  750.030976 2980.957987

$gamma
[1] 0.0 0.0 0.5 1.0 1.0
#simplify参数为TRUE时,sapply函数返回值数组化
sapply(e, fivenum,simplify=TRUE)
    alpha        beta gamma
[1,]     3    7.389056   0.0
[2,]     4   37.341843   0.0
[3,]     5  148.413159   0.5
[4,]     6  750.030976   1.0
[5,]     7 2980.957987   1.0

vapply函数

vapply函数与sapply函数也较为类似,不同的是它可以通过FUN.VALUE参数对返回值行名进行预定义。其用法如下:

vapply(X,FUN,FUN.VALUE,...,USE.NAMES=TRUE)

FUN.VALUE:通用型向量,以控制返回值的行名

用法实例:

g vapply(g,cumsum,FUN.VALUE=c('a'=0,'b'=0,'c'=0,'d'=0))
x1 x2
a  3  2
b  6  3
c  9  7
d 12 12

rapply函数

rapply函数可以理解为一个递归版本的lapply,同样只处理list类型的数据,对list中的每个元素进行递归遍历,如果list元素还包括子元素也需要继续遍历。其用法如下:

rapply(X, FUN,classes = ANY,deflt=NULL,how=c(unlist, replace, list),...)

X:list对象

FUN:作用在对象上的函数

classes:关于类名的字符向量,若为any则表示为任意类型

deflt:默认结果,若how参数选择了replace则不能使用

how:字符串匹配的三种结果

. . .:更多参数

rapply用法实例:

X rapply(X, sqrt, classes = "numeric", how = "replace")
[[1]]
[[1]]$a
[1] 1.772454

[[1]]$b
[[1]]$b$c
[1] 1

$d
[1] "a test"

mapply函数

mapply函数也是sapply函数的近亲,从函数名来看就知道mapply函数可以接受多个数据对象。其使用格式较前面几个有略微区别:

mapply(FUN,...,MoreArgs = NULL,SIMPLIFY = TRUE,USE.NAMES=TRUE)

FUN:作用对象函数







请到「今天看啥」查看全文