Friday, May 23, 2014

R apply family

R 的apply 类函数包括 apply, lapply, sapply, tapply, mapply 等。
这些函数经常被用来取代for loop 来进行矩阵,列表等的分割和计算处理。

首先谈 apply - apply 处理matrix 或者 array 的行或者列, 返回一个vector或者list.
基本使用为
apply ( x, 1, FUN)  对 x 的进行操作
apply ( x, 2, FUM) 对x 的进行操作

举例如下
m <- matrix(1:9,3,3, byrow=TRUE)
得到如下的一个矩阵
# 1 2 3
# 4 5 6
# 7 8 9
o1 <- apply(m,1,mean)
o1
[1] 2 5 8   可以看出来这个得到了每一行的平均值,第一行的平均为2,第二行为5,第三行为 8
同列也可以对列进行操作
o2 <- apply(m,2,mean)
o2
[1] 4 5 6




lappy 用来处理一个list,并且返回一个list

举例如下
l <- list(seq(1:5),seq(1:10),seq(1:25))
l
[[1]]
[1] 1 2 3 4 5
[[2]]
[1] 1 2 3 4 5 6 7 8 9 10
[[3]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

lapply(l,sum)
[[1]]
[1] 15
[[2]]
[1] 55
[[3]]
[1] 325




sapply 类似于lapply,但是返回一个vector 而非列表,在很多情况下便于阅读和后续处理,其实相当于unlist(lapply( x,FUN))
用sapply来处理上个例子
sapply(l,sum)
[1]  15  55 325
如果FUN运算的值是matrix的话,sapply会降解为list,举例说明
假设有如下list
l <- list(seq(1:4),seq(1:9),seq(1:25))
如果试图将list每一项转变为矩阵
首先定义函数
ToMatrix <- function(x){
root <- sqrt(length(x))
converted <- matrix(x,ncol=root,nrow=root,byrow=T)
return (converted)
}
z<-sapply(l,ToMatrix)
z

[[1]]
[,1] [,2]
[1,] 1 2
[2,] 3 4

[[2]]
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9

[[3]]
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 6 7 8 9 10
[3,] 11 12 13 14 15
[4,] 16 17 18 19 20
[5,] 21 22 23 24 25

str(z)
可以看到z 为list




tapply 用来处理含有factor的vector,tapply的第二项必须是factor

r<-c(1:100)
f <- rep(c("A","B","C","D"),each=25)
tapply(r,f,mean)
结果如下
A B C D
13 38 63 88




mapply 的用法为 mapply(FUN, …,  ... )
mapply的第一项是函数,后面省略号代表vector 或者list 的, 这些vector的每第N项都做为函数的参数传递到函数中。看起来很复杂,举例如下
fx <- function(x,y,z) { x+y^2+z^3}

首先定义一个函数,有三个参数x,y,z , 最后返回  x+y^2+z^3
假设有一个matrix m2
m2 <- matrix(1:6,2,3,byrow=T)
m2 如下两行三列
1   2   3
4   5   6

如果想对m2的每一列的值作为参数取得fx 的计算结果,就可以如下操作
mapply(fx, m2[,1],  m2[,2], m2[,3])
[1] 32   245

验证如下
1 + 2*2 + 3*3*3 = 1+4+27 =32
4 + 5*5 + 6*6*6 = 4+25 +216 =245

这个例子也可以用apply 来实现
apply(m2,1,function(x){x[1]+x[2]^2+x[3]^3})
[1]  32   245