R语言学习记录:apply、lapply、sapply、mapply、tapply函数

简介

批量处理函数有很重要的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
<think>好的,我现在需要回答用户关于R语言applysapplylapply函数的区别及使用场景的问题。首先,我得回忆一下这些函数的基本用法和区别。根据用户提供的引用内容,特别是引用[2]和引用[3],apply主要用于数组或矩阵的行或列操作,而lapplysapply处理列表或向量,其中sapply会简化输出结果。 接下来,我需要确定如何组织这些信息。用户要求结构清晰,逐步解决问题,所以可能需要先分别介绍每个函数,再比较它们的区别,最后给出使用场景的例子。同时,用户提到要生成相关问题,这部分需要放在最后。 然后,检查每个函数的语法和示例是否正确。比如,apply函数的使用示例是否正确,比如行列标准化。根据引用[1],apply的一个常见用途是行列标准化,所以需要确保示例代码正确。例如,使用apply(data, 1, function(x) (x - mean(x))/sd(x))来计算行的标准化,而列的标准化则是margin为2。 对于lapply,它返回列表,所以例子应该展示如何对列表中的每个元素进行操作,比如计算每个元素的平方根。而sapply则会根据结果简化成向量或矩阵,比如计算均值后返回向量。引用[3]中的例子是正确的,sapply(x, mean)会返回向量。 需要确保每个函数的特点都讲清楚,比如apply适用于数组,lapply处理列表返回列表,sapply简化结果。同时,结合用户提供的引用内容,引用[4]提到函数返回值放在列表里,所以lapply的输出符合这一结构。 最后,生成的相关问题需要与主题相关,比如询问性能差异、如何处理更复杂的数据结构,或者替代函数mapply的用法。确保问题覆盖用户可能感兴趣的扩展内容。 现在,我需要将这些思考整理成一个结构化的回答,确保每个部分都有对应的引用支持,并且语法正确,特别是数学表达式使用$...$格式,独立公式用$$...$$。不过,当前问题主要涉及代码示例,可能数学公式较少,但如果有的话需要正确应用格式。 总结步骤: 1. 分别介绍applylapplysapply的基本用法。 2. 对比三者的区别,强调输入和输出结构。 3. 提供具体的使用场景示例。 4. 引用对应的参考资料。 5. 生成相关问题。</think>### R语言apply系列函数的区别与用法 #### 1. **`apply()`函数** - **用途**:主要用于数组或矩阵的行或列操作,通过指定`MARGIN`参数(1为行,2为列)对数据逐行或逐列计算。 - **语法**: ```R apply(X, MARGIN, FUN, ...) ``` - **示例**: ```R # 对矩阵的行计算均值 data <- matrix(1:9, nrow=3) apply(data, 1, mean) # 输出:2 5 8 [^2] # 对列进行标准化 apply(data, 2, function(x) (x - mean(x))/sd(x)) [^1] ``` - **特点**:输入需为多维数据结构(如矩阵),输出类型取决于函数`FUN`的结果。 #### 2. **`lapply()`函数** - **用途**:对列表或向量中的每个元素应用函数,**始终返回列表**。 - **语法**: ```R lapply(X, FUN, ...) ``` - **示例**: ```R # 对列表中的每个元素计算平方根 x <- list(a=1:3, b=4:6) lapply(x, sqrt) # 输出:列表,每个元素为对应平方根 [^4] ``` - **特点**:输入为列表或向量,输出为列表,适合需要保留结果结构的场景。 #### 3. **`sapply()`函数** - **用途**:与`lapply()`类似,但尝试将结果简化为向量或矩阵。 - **语法**: ```R sapply(X, FUN, ..., simplify=TRUE) ``` - **示例**: ```R # 对列表中的每个元素计算均值(结果简化为向量) x <- list(a=1:3, b=4:6) sapply(x, mean) # 输出:向量c(2,5) [^3] ``` - **特点**:若所有结果长度相同且大于1,返回矩阵;若长度为1,返回向量。 #### 对比总结 | 函数 | 输入结构 | 输出结构 | 适用场景 | |----------|----------------|----------------|------------------------------| | `apply` | 矩阵/数组 | 向量/矩阵 | 行列聚合操作(如标准化) | | `lapply` | 列表/向量 | 列表 | 保留结果结构的逐元素计算| | `sapply` | 列表/向量 | 向量/矩阵/列表 | 简化结果的逐元素计算 | #### 使用场景示例 - **`apply`**:数据标准化、行列汇总统计。 - **`lapply`**:批量读取文件后处理,返回结构化结果。 - **`sapply`**:快速获取统计值(如均值、方差),简化输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值