apply函数家族
1.lapply
lapply输出的为一个列表
> students <- list(
+ a1=list(name="James",age=25,gender="M",interest=c("reading","writing")),
+ a2=list(name="Jenny",age=23,gender="F",interest=c("cooking")),
+ a3=list(name="David",age=24,gender="M",interest=c("running","basketball"))
+ )
+
> # 现在,构建一个字符向量,其中每一个元素都具有如下形式:
> # James,25 year-old man,loves reading,writing.
> ***# lapply处理***
> new_students <- lapply(students,function(x){
+ gender=switch(x$gender,"M"="man","F"="woman")
+ interests=paste(x$interest,collapse = ",")
+ sprintf("%s,%d year-old %s,loves %s",x$name,x$age,gender,interests)
+ })
> new_students
$a1
[1] "James,25 year-old man,loves reading,writing"
$a2
[1] "Jenny,23 year-old woman,loves cooking"
$a3
[1] "David,24 year-old man,loves running,basketball"
> do.call(rbind,new_students)
[,1]
a1 "James,25 year-old man,loves reading,writing"
a2 "Jenny,23 year-old woman,loves cooking"
a3 "David,24 year-old man,loves running,basketball"
2.sapply
因为列表不一定是存储数据的最好的容器,有时我们希望将结果放在一个向量或者矩阵。sapply()函数可以根据结果的结构将其合理化
> sapply(1:10,function(i)i^2)
[1] 1 4 9 16 25 36 49 64 81 100
> sapply(1:10,function(i)c(i,i^2))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 2 3 4 5 6 7 8 9 10
[2,] 1 4 9 16 25 36 49 64 81 100
其实这个我也可以用lapply,不过因为其结果返回的是列表,不好存储与查看,不太建议使用lapply(),而用sapply()函数。
vapply函数
ps:延伸出来的问题,在进行向量和列表运算的时候,我们发现向量可以向量化,而列表却不行
> t<-c(1,2)
> t^2
[1] 1 4
> l <- list(1,2)
> l^2
Error in l^2 : non-numeric argument to binary operator
vapply和sapply作用差不多,但是vapply比sapply更要规范一些,当像构成矩阵或向量时,发现输入的值不能满足这个返回形式,sapply会为了计算结果而变形,而vapply宁死不屈。
> x<- list(c(1,2),c(2,3),c(1,3))
> sapply(x,function(x)x^2)
[,1] [,2] [,3]
[1,] 1 4 1
[2,] 4 9 9
> vapply(x,function(i)i^2,numeric(2))
[,1] [,2] [,3]
[1,] 1 4 1
[2,] 4 9 9
> y <- list(c(1,2),c(3,4),c(5,6,7))
> sapply(y,function(i)i^2)
[[1]]
[1] 1 4
[[2]]
[1] 9 16
[[3]]
[1] 25 36 49
> vapply(y,function(i)i^2,numeric(2))
Error in vapply(y, function(i) i^2, numeric(2)) :
values must be length 2,
but FUN(X[[3]]) result is length 3
3.apply
apply()函数将一个函数应用到矩阵或数组的某个边际(margin)或维度上。
1表示行,2表示列
> mat <- matrix(c(1,2,3,4),nrow=2)
> mat
[,1] [,2]
[1,] 1 3
[2,] 2 4
> apply(mat,1,sum)
[1] 4 6
> apply(mat,2,sum)
[1] 3 7
4.mapply()函数
相比于sapply和vapply在一个向量上迭代,mapply可以在多个向量上进行迭代。mapply是sapply的多元版本。
mapply()所返回到结果是以向量一行一行的返回,与其他apply函数不同的是,它也有两个参数,不过第一个参数是函数,第二个参数才是要传入的数值。
> mapply(function(a,b,c){a*b+b*c+c*a},a=c(1,2),b=c(2,3),c=c(-1,-2))
[1] -1 -4
> df <- data.frame(x=c(1,2,3),y=c(3,4,5))
> mapply(function(x,y){c(x,y,x+y)},df$x,df$y)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 3 4 5
[3,] 4 6 8