简介

批量处理函数有很重要的apply族函数:lapply sapply apply tapply mapply。这些函数底层通过C实现,效率比手工遍历高效。apply族函数是高效能计算的运算向量化(Vectorization)实现方法之一,比起传统的for,while常常能获得更好的性能。

  1. apply : 用于遍历数组中的行或列,并且使用指定函数来对其元素进行处理。
  2. lapply : 遍历列表向量内的每个元素,并且使用指定函数来对其元素进行处理。返回列表向量
  3. sapply : 与lapply基本相同,只是对返回结果进行了简化,返回的是普通向量
  4. mapply: 支持传入两个以上的列表。
  5. tapply: 接入参数INDEX,对数据分组进行运算,就和SQL中的by group一样。

apply函数

对矩阵、数据框、数组(二维、多维)等矩阵型数据,按行或列应用函数FUN进行循环计算,并以返回计算结果。
apply(X, MARGIN, FUN, …)

  1. X:数组、矩阵、数据框等矩阵型数据
  2. MARGIN:按行计算或按列计算,1表示按行,2表示按列
  3. FUN:自定义的调用函数,如mean/sum等(其结果与colMeans,colSums,rowMeans,rowSums是一样的)
> a<-matrix(1:12,c(3,4))
> a
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> apply(a,1,function(x) sum(x)+2)
[1] 24 28 32
> apply(a,1,function(x) x^2)
     [,1] [,2] [,3]
[1,]    1    4    9
[2,]   16   25   36
[3,]   49   64   81
[4,]  100  121  144

lapply函数

对列表、数据框按列进行循环,输入必须为列表(list),返回值为列表(list)。
lapply(X, FUN, …)

  1. X:列表、数据框
  2. FUN:自定义的调用函数
b<-list(x = 1:10, y = matrix(1:12, 3, 4))
$x
 [1]  1  2  3  4  5  6  7  8  9 10

$y
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
lapply(b, sum)  #求列表中各元素的和
$x
[1] 55

$y
[1] 78
> a=data.frame(matrix(1:12,c(3,4)))
> a
  X1 X2 X3 X4
1  1  4  7 10
2  2  5  8 11
3  3  6  9 12
> names(a)
[1] "X1" "X2" "X3" "X4"
> str(a)
'data.frame':	3 obs. of  4 variables:
 $ X1: int  1 2 3
 $ X2: int  4 5 6
 $ X3: int  7 8 9
 $ X4: int  10 11 12
 > lapply(a, function(x) x+3)
$X1
[1] 4 5 6

$X2
[1] 7 8 9

$X3
[1] 10 11 12

$X4
[1] 13 14 15

> a1 <- lapply(a, function(x) sum(x)+3)
> a1
$X1
[1] 9

$X2
[1] 18

$X3
[1] 27

$X4
[1] 36
> a1[1]
$X1
[1] 9

> a1[[1]]
[1] 9

sapply函数

类似于lapply函数,但输入为列表(list),返回值为向量。
sapply(X, FUN, …,simplify )

  1. X:列表、矩阵、数据框
  2. FUN:自定义的调用函数
  3. simplify=F:返回值的类型是list,此时与lapply完全相同
    simplify=T(默认值):返回值的类型由计算结果定,如果函数返回值长度为1,则sapply将list简化为vector;如果返回的列表中每个元素的长度都大于1且长度相同,那么sapply将其简化位一个矩阵
> a=data.frame(matrix(1:12,c(3,4)))
> a   #"list"
  X1 X2 X3 X4
1  1  4  7 10
2  2  5  8 11
3  3  6  9 12
> str(a)
'data.frame':	3 obs. of  4 variables:
 $ X1: int  1 2 3
 $ X2: int  4 5 6
 $ X3: int  7 8 9
 $ X4: int  10 11 12
> a2 <- lapply(a, function(x) x+3)
> a2  #"list"
$X1
[1] 4 5 6

$X2
[1] 7 8 9

$X3
[1] 10 11 12

$X4
[1] 13 14 15
> str(a2)
List of 4
 $ X1: num [1:3] 4 5 6
 $ X2: num [1:3] 7 8 9
 $ X3: num [1:3] 10 11 12
 $ X4: num [1:3] 13 14 15
> a3 <- sapply(a, function(x) x^2)
> a3  #"numeric"
     X1 X2 X3  X4
[1,]  1 16 49 100
[2,]  4 25 64 121
[3,]  9 36 81 144
> str(a3)
 num [1:3, 1:4] 1 4 9 16 25 36 49 64 81 100 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:4] "X1" "X2" "X3" "X4"
> b<-list(x = 1:10, y = matrix(1:12, 3, 4))
> sapply(b, sum)
 x  y 
55 78 

sapply函数可提取列表中数据

y<-c("100-D","100-A","110-c","110-A")
z<-strsplit(y,"-")
sapply(z,"[",1) #提取列表第1个元素
sapply(z,"[",2) #提取列表中第2个元素
第一行:定义一个向量y
第二行:使用strsplit函数对向量y 按照“-”符号进行分割,得到一个列表z
第三行:使用sapply函数提取列表z的第1个和第2个位置元素,输出结果如下:
[1] "100" "100" "110" "110"
> sapply(z,"[",2) #提取列表中第2个元素
[1] "D" "A" "c" "A"

mapply函数

mapply是sapply的多变量版本(multivariate sapply)。
mapply(FUN, …, MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)

> a <- mapply(function(x,y) x^y, c(1:5), c(1:5))
> a
[1]    1    4   27  256 3125
> mode(a)
[1] "numeric"
> str(a)
 num [1:5] 1 4 27 256 3125
> names(a)
NULL
> b<-matrix(1:12,c(3,4),dimnames=list(c("a","b","c"),c("A","B","C","D")))
> b
  A B C  D
a 1 4 7 10
b 2 5 8 11
c 3 6 9 12
> mapply(sum, b[,1],b[,3],b[,4])
 a  b  c 
18 21 24 
> mapply(sum,b[1,],b[2,],b[3,])
 A  B  C  D 
 6 15 24 33 

tapply函数

将数据按照不同方式分组,生成类似列联表形式的数据结果。
tapply(X, INDEX, FUN = NULL, …, default = NA, simplify = TRUE)

  1. X:数组、矩阵、数据框等分割型数据向量
  2. INDEX:一个或多个因子的列表(因子列表),每个因子的长度都与x相同
  3. FUN: 自定义的调用函数
  4. simplify指是否简化输入结果(考虑sapply对于lapply的简化)

代码举例

manager <- c(1, 2, 3, 4, 5)
country <- c("US", "US", "UK", "UK", "UK")
gender <- c("M", "F", "F", "M", "F")
age <- c(32, 45, 25, 39, 99)
leadership <- data.frame(manager, country, gender, age)
tapply(leadership$age, leadership$country, mean)	#求在不同country水平下的age的均值

tapply(leadership$age, list(leadership$country, leadership$gender), mean)   #求在不同country和gender交叉水平下的age的均值, 输出得到矩阵数据

输出结果

     UK       US 
54.33333 38.50000 

    F  M
UK 62 39
US 45 32
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐