之前的博客《R数据分析当中的化整为零(Split-Apply-Combine)策略》以及《关于R当中的tapply》有提到一些关于lapply, sapply, vapply和tapply的内容。对于mapply只是粗粗带过。但很多时候,使用mapply可以帮助我们大大提高效率。我们先来看一个非常时用的函数yapply。
yapply <- function(X,FUN, ...) { index <- seq(length.out=length(X)) namesX <- names(X) if(is.null(namesX)) namesX <- rep(NA,length(X)) FUN <- match.fun(FUN) fnames <- names(formals(FUN)) if( ! "INDEX" %in% fnames ){ formals(FUN) <- append( formals(FUN), alist(INDEX=) ) } if( ! "NAMES" %in% fnames ){ formals(FUN) <- append( formals(FUN), alist(NAMES=) ) } mapply(FUN,X,INDEX=index, NAMES=namesX,MoreArgs=list(...)) } |
使用这个yapply,它非常类似lapply,所不同的是,它可以在函数中使用NAMES以及INDEX两个变量,这两个变量分别是list的names以及索引号。当有两个索引号相关的数据,或者名称相关的数据需要在一个lapply中进行操作的时候,就变得非常方便。比如
> a <- 1:10 > names(a) <- letters[1:10] > b <- 2:11 > names(b) <- letters[2:11] > a a b c d e f g h i j 1 2 3 4 5 6 7 8 9 10 > b b c d e f g h i j k 2 3 4 5 6 7 8 9 10 11 > aplusb<-function(.a,.b){.a+.b} > mapply(aplusb,as.list(a),as.list(b)) a b c d e f g h i j 3 5 7 9 11 13 15 17 19 21 > aplusbByname <- function(.a, NAMES){if(NAMES %in% names(b)) .a+b[[NAMES]] else .a} > mapply(aplusbByname,as.list(a),names(a)) a b c d e f g h i j 1 4 6 8 10 12 14 16 18 20 |
mapply的原型是:mapply(FUN, …, MoreArgs = NULL, SIMPLIFY = TRUE,
USE.NAMES = TRUE)
其中…可以是一系列长度相等的list/vector等。它们是做为FUN的参数一一对应的传入FUN当中去使用。由此可以,mapply是处理多个有关联的list以及vector的好帮手。