在R语言中,apply系列函数用于向量、矩阵、数据框应用指定函数,并返回函数应用结果值,这些函数会一次性地对整体数据施加函数运算,采用的是向量计算方式,所以执行速度非常快
一、Apply()函数
apply函数按照矩阵的行或列方向应用指定函数
使用apply函数进行按行求和
初始矩阵
> d<-matrix(1:9,ncol=3)
> d
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
我们可以使用apply函数对矩阵的每行应用到sum函数即可
> apply(d,1,sum)#这边设置MARGIN为1,即行模式
[1] 12 15 18
如果我们想进行按列求和,将MARGIN设置为2即可
> apply(d,2,sum)
[1] 6 15 24
当然,R语言直接提供了一些函数帮助我们直接对行和列求和,或者求平均值
例如
> colSums(d)
[1] 6 15 24
> rowMeans(d)
[1] 4 5 6
二、Lapply()函数
Lapply()可以以列表的形式返回应用函数的结果
但从使用角度来看,向量与数据框比列表更直观,所以必须要转换lapply()的结果,我们可以用下面两个函数进行转换
例如:我们使用lapply()函数对向量进行乘2运算,然后将其转换为向量
> (result<-lapply(1:3,function(x){x*2}))
[[1]]
[1] 2
[[2]]
[1] 4
[[3]]
[1] 6
> unlist(result)
[1] 2 4 6
Lapply()函数可以接受列表作为参数
例如:
> (x<-list(a=1:3,b=4:6))
$a
[1] 1 2 3
$b
[1] 4 5 6
> lapply(x, mean)
$a
[1] 2
$b
[1] 5
同时,也可以直接向数据框应用lapply()函数
例如:
> H<-data.frame(x=c(1:3),y=c(4:6),z=c(7:9))
> lapply(H, mean)
$x
[1] 2
$y
[1] 5
$z
[1] 8
从上可知,使用lapply()函数处理过的数据框后得到的列表,有时可能需要列表再次进行转换为数据框,通常会进行以下几个阶段
1.使用unlist()函数,将列表转换为对象
2.使用matrix()函数,将向量转化为矩阵
3.使用as.data.frame()函数,将矩阵转换为数据框
4.使用names()函数,从列表获取变量名,赋给数据框的各列
不过,我们可以使用do.call()函数进行类型转换
例如:我们将lapply()函数返回的列表中的个元素作为参数传递给cbind函数
> data.frame(do.call(cbind,lapply(H,mean)))
x y z
1 2 5 8
上述两种方法中,使用第一种方法先用unlist()函数将列表转换为向量,再使用matrix()函数将向量转换为矩阵的时候会出现一个问题,就是使用unlist()哈桑农户将列表转换为向量以后,由于向量只能保存1种数据类型,所以转换过程中,所有数据都会被转换成统一数据类型。列表中同时存在字符串和数值时,使用unlist()函数将列表转换为向量后, 所有的元素都会被强制转换为同一种数据类型
例如
> h<-list(data.frame(name="foo",value=1),data.frame(name="bar",value=2))
> unlist(h)
name value name value
"foo" "1" "bar" "2"
因此,当列表中有不同数据类型的数据时,需要使用do.call()函数进行类型转换
例如:
> h<-list(data.frame(name="foo",value=1),data.frame(name="bar",value=2))
> do.call(rbind,h)
name value
1 foo 1
2 bar 2
三、Sapply()函数
Sapply()函数与lapply()函数类似,但以矩阵、向量等数据类型返回结果
例如:
> lapply(H,mean)
$x
[1] 2
$y
[1] 5
$z
[1] 8
> sapply(H,mean)
x y z
2 5 8
> class(sapply(H,mean))
[1] "numeric"
我们可以使用as.data.frame()函数将sapply()函数返回的向量进一步转换为数据框,但是必须要用t()函数进行转置,否则数据框会行列互换
例如:
> x<-sapply(H,mean)
> as.data.frame(x)
x
x 2
y 5
z 8
> t(x)
x y z
[1,] 2 5 8
在处理包含多列的数据框时,常常需要判断各列的数据类型,比如判断某列中保存的数据是否为数值,若使用sapply()函数能够很方便地进行判断
例如:
> sapply(H,class)
x y z
"integer" "integer" "integer"
如果sapply()函数的参数传入的函数返回值时长度大于1的向量,那么sapply()函数将返回矩阵
例如:
> y<-sapply(H,function(x){x>2})
> class(y)
[1] "matrix"
> y
x y z
[1,] FALSE TRUE TRUE
[2,] FALSE TRUE TRUE
[3,] TRUE TRUE TRUE
sapply函数返回的是向量和矩阵,但是向量和矩阵只能保存一种数据类型,因此sapply()函数的参数传入FUN函数的返回值中,不能混有多种数据类型,否则需要返回列表的lapply()函数
四、Tapply()函数
Tapply()函数会先对数据进行分组,然后将函数应用到各组
例如:
求1~10的总和
> tapply(1:10,rep(1,10),sum)
1
55
划分奇偶数,并算出其总和
> tapply(1:10,1:10%%2==1,sum)
FALSE TRUE
30 25
五、Mapply()函数
Mapply()函数和sapply()函数类似,但它可以将多个参数传递给指定函数。Mapply()函数的的一个参数是待应用的FUN函数,它接受多个参数,要传递给FUN()函数的参数作为数据保存时,mapply()函数将保存在数据中的值转化为参数传递给FUN函数,并执行调用
例如,我们使用mapply()函数批量生成正态分布数据
假设要生成如下参数的正太分布数据
注:使用mapply()函数时,如果给定多个数据,则这些数据第一个元素组成一组,作为参数传递给FUN函数,然后第二个元素组成一组,作为参数传递给FUN函数,以此类推
> mapply(rnorm,c(1,2,3),c(0,10,100),c(1,1,1))
[[1]]
[1] -0.9214251
[[2]]
[1] 10.60762 11.34686
[[3]]
[1] 98.75579 98.46603 99.04913
我们也可以使用mapply()函数求矩阵各列平均值
> H<-data.frame(x=c(1:3),y=c(4:6),z=c(7:9))
> H
x y z
1 1 4 7
2 2 5 8
3 3 6 9
> mapply(mean,H)
x y z
2 5 8