R apply()、lapply()、sapply()、tapply() 及其示例

本教程旨在介绍apply()函数集合。apply()函数是所有集合中最基础的。我们还将学习sapply()、lapply()和tapply()。apply集合可以被看作是循环的替代品。

如果您使用Anaconda安装R,apply()集合将与r essential包捆绑在一起。R中的apply函数可以接收多个函数,对对象集合(数据框、列表、向量等)执行冗余应用。apply()的目的主要是避免显式使用循环结构。它们可以用于输入列表、矩阵或数组,并应用一个函数。任何函数都可以传递给apply()。

apply() 函数

apply() 以数据框或矩阵为输入,并以向量、列表或数组的形式输出。Apply R中的函数主要用于避免显式使用循环结构。它是所有集合中最基础的,可用于矩阵。

此函数接受3个参数

apply(X, MARGIN, FUN)
Here:
-x: an array or matrix
-MARGIN:  take a value or range between 1 and 2 to define where to apply the function:
-MARGIN=1`: the manipulation is performed on rows
-MARGIN=2`: the manipulation is performed on columns
-MARGIN=c(1,2)` the manipulation is performed on rows and columns
-FUN: tells which function to apply. Built functions like mean, median, sum, min, max and even user-defined functions can be applied>

最简单的例子是对所有列的总和求和。代码 apply(m1, 2, sum) 将对 5x6 矩阵应用 sum 函数,并返回数据集中可访问的每一列的总和。

m1 <- matrix(C<-(1:10),nrow=5, ncol=6)
m1
a_m1 <- apply(m1, 2, sum)
a_m1

输出

Apply() Function Example in R
R 中的 apply() 函数示例

最佳实践:在将值打印到控制台之前先存储它们。

lapply() 函数

lapply() 函数对于对列表对象执行操作非常有用,并返回与原始集合长度相同的列表对象。lappy() 返回一个与输入列表对象长度相似的列表,其中每个元素都是将 FUN 应用于列表相应元素的结果。Lapply in R 以列表、向量或数据框为输入,并以列表为输出。

lapply(X, FUN)
Arguments:
-X: A vector or an object
-FUN: Function applied to each element of x	

lapply() 中的 l 代表 list。lapply() 和 apply() 之间的区别在于返回的输出。lapply() 的输出是一个列表。lapply() 可用于其他对象,如数据框和列表。

lapply() 函数不需要 MARGIN。

一个非常简单的例子是将矩阵中的字符串值转换为小写,使用 tolower 函数。我们构造一个包含著名电影名称的矩阵。名称是大写格式。

movies <- c("SPYDERMAN","BATMAN","VERTIGO","CHINATOWN")
movies_lower <-lapply(movies, tolower)
str(movies_lower)

输出

## List of 4
## $:chr"spyderman"
## $:chr"batman"
## $:chr"vertigo"
## $:chr"chinatown"

我们可以使用 unlist() 将列表转换为向量。

movies_lower <-unlist(lapply(movies,tolower))
str(movies_lower)

输出

##  chr [1:4] "spyderman" "batman" "vertigo" "chinatown"

sapply() 函数

sapply() 函数以列表、向量或数据框为输入,并以向量或矩阵为输出。它对于对列表对象执行操作非常有用,并返回与原始集合长度相同的列表对象。Sapply function in R 的作用与 lapply() 函数相同,但返回的是一个向量。

sapply(X, FUN)
Arguments:
-X: A vector or an object
-FUN: Function applied to each element of x

我们可以从 cars 数据集中测量汽车的最小速度和刹车距离。

dt <- cars
lmn_cars <- lapply(dt, min)
smn_cars <- sapply(dt, min)
lmn_cars

输出

## $speed
## [1] 4
## $dist
## [1] 2
smn_cars

输出

## speed  dist 
##     4     2
lmxcars <- lapply(dt, max)
smxcars <- sapply(dt, max)
lmxcars

输出

## $speed
## [1] 25
## $dist
## [1] 120
smxcars

输出

## speed  dist 
##    25   120

我们可以使用用户定义的函数来执行 lapply() 或 sapply()。我们创建一个名为 avg 的函数来计算向量的最大值和最小值的平均值。

avg <- function(x) {  
  ( min(x) + max(x) ) / 2}
fcars <- sapply(dt, avg)
fcars

输出

## speed  dist
##  14.5  61.0

Sapply in R 比 lapply() 在返回的输出方面更有效率,因为 sapply() 直接将值存储到向量中。在下一个示例中,我们将看到情况并非总是如此。

我们可以在下表中总结 apply()、sapply() 和 lapply() 之间的区别

函数 参数 目标 输入 输出
apply apply(x, MARGIN, FUN) 将函数应用于行、列或两者 数据框或矩阵 向量、列表、数组
lapply lapply(X, FUN) 将函数应用于输入的所有元素 列表、向量或数据框 列表
sapply sapply(X, FUN) 将函数应用于输入的所有元素 列表、向量或数据框 向量或矩阵

切片向量

我们可以互换使用 lapply() 或 sapply() 来切片数据框。我们创建一个名为 below_average() 的函数,该函数接受一个数值向量,并返回一个仅包含严格高于平均值的向量。我们使用 identical() 函数比较两个结果。

below_ave <- function(x) {  
    ave <- mean(x) 
    return(x[x > ave])
}
dt_s<- sapply(dt, below_ave)
dt_l<- lapply(dt, below_ave)
identical(dt_s, dt_l)

输出

## [1] TRUE

tapply() 函数

tapply() 计算向量中每个因子变量的度量(均值、中位数、最小值、最大值等)或函数。它是一个非常有用的函数,允许您创建向量的子集,然后对每个子集应用一些函数。

tapply(X, INDEX, FUN = NULL)
Arguments:
-X: An object, usually a vector
-INDEX: A list containing factor
-FUN: Function applied to each element of x

数据科学家或研究人员的工作部分是计算变量的摘要。例如,测量均值或根据某个特征对数据进行分组。大多数数据都按 ID、城市、国家等分组。按组汇总会揭示更有趣的模式。

为了理解它是如何工作的,让我们使用 iris 数据集。这个数据集在机器学习界非常有名。此数据集的目的是预测三个花卉物种:萼片、变色萼片、弗吉尼亚花的类别。该数据集收集了每个物种的长度和宽度信息。

作为先前的工作,我们可以计算每个物种长度的中位数。R 中的 Tapply 是执行此计算的快速方法。

data(iris)
tapply(iris$Sepal.Width, iris$Species, median)

输出

##     setosa versicolor  virginica 
##        3.4        2.8        3.0