【R语言】apply函数族

时间:2022-07-04 01:39:38

    R语言apply系列函数的基本作用是对数组(array,可以是多维)或者列表(list)按照元素或元素构成的子集合进行迭代,并将当前元素或子集合作为参数调用某个指定函数。vector是一维的array,dataframe可以看作特殊的list。

 

作用目标

在每个元素上应用

在子集合上应用

array

apply

tapply

list

lapply (...)

by

 

    其中 lapply(...) 为一族函数,包括简化版: sapply,递归版: rapply。其中sapply又可分为可设置返回值模板vapply和多变量版mapply。另外vector比较特殊,vector是一维的array,但是却不全是和array使用相同的函数。在按元素迭代的情况下,使用和list一样的 lapply 函数;而在按子集合迭代的情况下, tapply 和 by 都能用,只是返回值形式不同。

 

1.    apply函数

在array上,沿margin方向,依次调用 FUN,返回结果通常为Array类型,如果返回值的向量长度不等,则返回List对象。margin表示数组引用的第几维下标(即array[index1, index2, ...]中的第几个index),margin = 1表示行,2表示列,c(1,2) 表示行和列。

–       举例1:

# 二维矩阵对象

x <- cbind(x1 = 3, x2 = c(4:1, 2:5))

dimnames(x)[[1]] <- letters[1:8]

apply(x, 2, mean, trim = .2)

apply(x, 1, mean, trim = .2)

apply(x, 2, sort)

 

–       举例2:

#三维数组对象,数据向量中的值被赋给数组中的值时,将遵循“主列顺序”,即第一个下标变化最快,最后的下表变化最慢。

z <- array(1:24, dim = 2:4)

apply(z, 3, mean)

apply(z, 1:2, function(x) seq_len(max(x)))

apply(z, 3, function(x) seq_len(max(x)))

 

注: 虽然vector是一维的array,但是不能使用apply,array只能用在二维及以上的array上,因为apply要求dim(X)的值必需是正数,vector对象的dim值为NULL。

 

2.    tapply函数

        按 indices 中的值分组,把相同值对应下标的array中的元素形成一个集合,应用到 FUN 。类似于group by indices的操作。当simplify = TRUE(默认)时,如果 FUN 返回的是一个值, tapply 返回Array,空值用NULL表示;若 FUN 返回多个值, tapply 返回list,空值使用NA表示。当simplify = FALSE时,tapply 都返回list 对象。 Array或list的长度和 indices 中不同值的个数相等。

        当 FUN 为 NULL 的时候,返回一个长度和array中元素个数相等的vector,指示分组的结果,vector中相等的元素所对应的下标属于同一组。例如,返回c(1, 2, 1, 3, 2), 表示根据传入的 indices ,第1、3个元素作为一组,第2、5个元素作为一组,第4个元素作为一组。

–       举例1:

#tapply应用于vector

height <- c(174, 165, 180, 171, 160)

sex<-c("F","F","M","F","M")

#返回vector

tapply(height, sex, mean)

#返回list

tapply(height, sex, mean, simplify = F)

#因为函数fivenum返回多值,即使simplify = TRUE,也是返回list对象

tapply(height, sex, fivenum)

 

–       举例2:

#tapply应用于matrix

m <- matrix(c(1:10), nrow=2)

ind <- matrix(c(rep(1,5),rep(2,5)), nrow=2)

tapply(height, sex)

tapply(m, ind, mean)

tapply(m, ind, fivenum)

 

–       举例3:

#tapply实现crosstable功能

df<-data.frame(year=kronecker(2001:2003,rep(1,4)),loc=c('beijing','beijing','shanghai','shanghai'), type=rep(c('A','B'),6), sale=rep(1:12))

#以年份为行、地区为列计算销售总量

tapply(df$sale, df[,c('year','loc')], sum)

#以年份为行,类别为列计算销售总量

tapply(df$sale, df[,c('year','type')], sum)

#以年份,地区和类别计算销售总量

tapply(df$sale, df[,c('year','loc','type')],sum)

 

3.    lapply函数

在 list 上逐个元素调用 FUN 。可以用于dataframe上,因为dataframe是一种特殊形式的list。若对象不是list和表达式类型,会先强制转换为list后再应用于FUN函数。

–       举例1:

#lapply应用于matrix

lst <- list(a=c(1:5), b=c(6:10))

lapply(lst, mean)

 

–       举例2:

# List会先强制转换为List后再求均值,这时每一个元素都是一个list的对象

x <- 1:3

lapply(x, mean)

 

–       举例3:

# dataframe使用lapply

df <- data.frame(x=c(1:3),y=c(6:8))

lapply(df, mean)

 

4.    sapply函数

      比 lapply 多了一个 simplify 参数。如果 simplify=FALSE ,则等价于lapply 。否则,在上一种情况的基础上,将 lapply 输出的list简化为vector或matrix,默认的simplify=TRUE。

–       举例1:

x<-list(a= 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE))

#simplify = FALSE,lapply 返回list对象

sapply(x, mean, simplify = FALSE, USE.NAMES = FALSE)

 

–       举例2:

#simplify = TRUE,以向量形式返回结果

sapply(x, mean, simplify = TRUE, USE.NAMES = FALSE)

 

–       举例3:

#默认的simplify=TRUEfivenum返回多值,因此最终返回结果为matrix对象

sapply(x, fivenum)

 

5.    vapply函数

      vapply 类似于 sapply (但返回类型只包含Array) ,但是提供了第三个参数 FUN.VALUE 用以指明返回值的形式,可以看作返回值的模板。vapply会检测FUN的所有值是否与FUN.VALUE兼容,以使他们具有相同的长度和类型,为了实现类型的兼容,类型存在被强制转换为更高类型的可能,转换顺序:

 logical < integer < double < complex

–       举例1:

#返回值的类型和长度要和预设值一致

x<-list(a= 1:10, beta = exp(-3:3), logic =c(TRUE,FALSE,FALSE,TRUE))

vapply(x, function(x) {c(mean(x),sd(x))}, FUN.VALUE = c(0, 0), USE.NAMES = TRUE)

 

6.    mapply函数

      mapply 是多变量版的 sapply(返回类型只包含Array) ,参数(...)部分可以接收多个数据, mapply 将FUN 应用于这些数据的第一个元素组成的数组,然后是第二个元素组成的数组,以此类推,直到用于每个参数的元素,要求多个数据的长度相同,或者是整数倍关系,如果参数长度不同,长度短的参数会被循环使用。返回值是array或list(如果返回值的向量长度不等,则返回List对象),取决于 FUN 返回值是一个还是多个。

–       举例1:

#对两个list对象的元素依次求和

mapply(sum, list(a=1,b=2,c=3), list(a=10,b=20,d=30))

 

–       举例2:

#对第一和第二个对象使用rep函数,对象二长度较短会被循环使用

#返回对象长度不同,返回list对象

mapply(rep, c(1,2,4,5), c(3,4))

#返回对象长度相同同,返回matrix对象

mapply(rep, c(1,2,4,5), c(3,4)) 

 

–       举例3:

#函数返回多值,因此返回matrix对象

mapply(function(x,y) c(x+y, x^y), c(1:5), c(1:5))

 

–       举例4:

#使用MoreArgs给出rep的参数x

mapply(rep, times = 1:2, MoreArgs = list(x = 42))

 

7.    rapply函数

  •       rapply 是递归版的 lappy 。基本原理是对list作遍历,如果其中有的元素仍然是list,则继续遍历;对于每个非list类型的元素,如果其类型是 classes 参数指定的类型之一,则调用 FUN 。classes="ANY"表示匹配所有类型。how参数用来指定操作方式,有三种:"replace"对元素类型在 classes 中的直接用调用 FUN,不在的保留原始值。
  •  "list" 新建一个list,元素类型在 classes 中的,调用 FUN ;不在 classes 中的类型,使用 deflt 。会保留原始list的结构。
  • "unlist" 相当于对"list"模式下的结果调用 unlist(recursive=TRUE)

–       举例1:

X <- list(list(a = pi, b =list(c = 2)), d = "a test")

#X中的numeric类型的元素使用sqrt函数,保留非numeric元素值不变

rapply(X, sqrt, classes = "numeric", how ="replace")

 

–       举例2:

#X中的character类型的元素使用nchar函数,保留非nchar元素值不变

rapply(X, nchar, classes = "character", how ="replace")

 

–       举例3:

#X中的character类型的元素使用nchar函数,非character元素使用默认值deflt

rapply(X, nchar, classes = "character", deflt =as.integer(NA), how = "list")

 

–       举例4:

#X中的character类型的元素使用nchar函数,非character元素使用默认值deflt,返回结果使用unlist函数

rapply(X, nchar, classes = "character", deflt =as.integer(NA), how = "unlist")

 

–       举例5:

#X中的character类型的元素使用nchar函数,没有设置deflt参数会直接舍弃非character元素,返回结果使用unlist函数

rapply(X, nchar, classes = "character", how ="unlist")

#对于how=list的情况,没有设置deflt参数会使用默认值NULL

rapply(X, nchar, classes = "character", how = "list")

 

–       举例6:

#X中的numeric类型的元素使用log函数,函数参数为base=2

rapply(X, log, classes = "numeric", how ="replace", base = 2)

 

8.    eapply函数

对environment中命名值进行FUN计算后返回一个列表值,用户可以请求所有使用过的命名对象。

–       举例1:

env <- new.env(hash = FALSE)

env$a <- 1:10

env$beta <- exp(-3:3)

env$logic <- c(TRUE, FALSE, FALSE, TRUE)

# 列出环境中的对象

utils::ls.str(env)

# 对每个元素计算均值

eapply(env, mean)

 

各方法详细总结见下表:

函数

用法

输入

输出

语法

apply

对阵列行或者列使用函数

Array

Array/List

apply(X, MARGIN, FUN, ...)

lapply

对列表或者向量使用函数

List/expression

List

lapply(X, FUN, ...)

sapply

对列表或者向量使用函数

List/expression

List/Array

sapply(X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)

vapply

对列表或者向量使用函数

List/expression

Array

vapply(X, FUN, FUN.VALUE, ..., USE.NAMES = TRUE)

tapply

对不规则阵列使用函数

Array

Array/List

tapply(X, INDEX, FUN = NULL, ..., simplify = TRUE)

eapply

对环境中的值使用函数

Values in an Environment

List

eapply(env, FUN, ..., all.names = FALSE, USE.NAMES = TRUE)

mapply

对多个列表或者向量参数使用函数

List/Array

List/Array

mapply(FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)

rapply

运用函数递归产生列表

List

List/Vector

rapply(object, f, classes = "ANY", deflt = NULL,how = c("unlist", "replace", "list"), ...)