- apply()将数据框或矩阵作为输入,并以矢量,列表或数组形式输出。apply()函数主要用于避免重复使用循环结构。它是所有可以在矩阵上使用的最基本的集合。
最简单的示例是对所有列求和。代码apply(m1,2,sum)将sum函数应用于矩阵5x6,并返回数据集中可访问的每一列的总和。
m1 <- matrix(C<-(1:10),nrow=5, ncol=6) 5行6列,默认按列排序
m1
a_m1 <- apply(m1, 2, sum) # 对m1矩阵的列(MARGIN=2)求sum
a_m1
- lapply()函数可用于对列表对象执行操作,并返回与原始集合长度相同的列表对象。
lapply()中的l代表列表。lapply()和apply()之间的区别在于输出返回之间。lapply()的输出是一个列表。因此,lapply()函数不需要MARGIN。
movies <- c("SPYDERMAN","BATMAN","VERTIGO","CHINATOWN")
movies_lower <-lapply(movies, tolower) # tolower函数将所有的大写电影名改成小写
str(movies_lower)
我们可以使用unlist()将列表转换为向量。
films_lower <- unlist(lapply(movies,tolower)) # 使用unlist()将列表转换为向量
str(movies_lower)
- sapply()函数将列表,向量或数据帧作为输入,并以向量或矩阵形式输出。sapply()函数执行的功能与lapply()函数相同,但返回一个向量。
那和 unlist(lapply()) 有什么区别吗?结果显示:没有=。=
好吧肯定是有区别的,查阅了一下资料: https://stackoverflow.com/questions/18761541/why-is-unlistlapply-faster-than-sapply
资料告诉我们:
We don't need
sapply
. It exists purely for convenience. – Roland (我们不需要sapply
。它纯粹是为了方便而存在。)除了运行以外
lapply
,还sapply
可以运行simplify2array
以尝试将输出拟合到数组中。为了弄清楚这是否可行,该函数需要检查所有单个输出的长度是否都相同:这是通过花费大量费用unique(lapply(..., length))
来解决的,该费用占了您所看到的大部分时间差。 —— flodel正如droopy和Roland所指出的那样,
sapply
是lapply的
包装函数,旨在方便使用。sapply
使用simplify2array,
速度比unlist
慢。 —— user1981275
跳过这些,直接看代码:
dt <- cars
lmn_cars <- lapply(dt, min) # 测量汽车的最小速度和最小停车距离
smn_cars <- sapply(dt, min)
lmn_cars
smn_cars
unlist_lmn_cars <- unlist( lmn_cars )
unlist_lmn_cars
> unlist_lmn_cars == smn_cars
speed dist
TRUE TRUE
> identical(unlist_lmn_cars,smn_cars)
[1] TRUE
得到这个结果后,我们应该如何分析呢?欢迎读者赐教!
- tapply()计算向量中每个因子变量的度量函数(均值,中位数,最小值,最大值等)。
data(iris) # 使用虹膜数据集。该数据集的目的是预测三种花类中的每一种的类别。
tapply(iris$Sepal.Width, iris$Species, median) # 计算每个物种Species的宽度Width的中位数
声明:上文参考https://www.jianshu.com/p/59fb24ca2ea7 ,原作者你有康娜可爱吗,写的真好~简单做了些注释
- Examples
## Compute row and column sums for a matrix: 分别计算矩阵的行列的和
x <- cbind(x1 = 3, x2 = c(4:1, 2:5)) # 向量,2列8行
# dimnames(x) 包含x的行列名, dimnames(x)[[1]] 是行名,dimnames(x)[[2]] 是列名
dimnames(x)[[1]] <- letters[1:8] # 将行名设置为a到h
# apply(X, MARGIN, FUN, ...) FUN后面的内容都是FUN的可选参数设置
# trim 会分别去除百分之多少的最大值和最小值
apply(x, 2, mean, trim = .2) # 去掉20%的最大值和最小值,对x按列求和
col.sums <- apply(x, 2, sum) # 列和
row.sums <- apply(x, 1, sum) # 行和
# cbind(x, Rtot = row.sums) 生成向量 列1=x1,列2=x2,列3=各行之和 共3列8行
# Ctot = c(col.sums, sum(col.sums)) 生成向量,由x1列1和,x2列和,总和 组成 3列1行
# 按行合并,生成3列(8+1)行的向量组
rbind(cbind(x, Rtot = row.sums), Ctot = c(col.sums, sum(col.sums)))
stopifnot( apply(x, 2, is.vector)) # stopifnot没有报错,说明x每列都是向量
## Sort the columns of a matrix 对矩阵按列排序
apply(x, 2, sort)
## keeping named dimnames 保留行列名的命名
# dimnames(x) 包含x的行列名, dimnames(x)[[1]] 是行名,dimnames(x)[[2]] 是列名
# 给行列名取名
names(dimnames(x)) <- c("row", "col")
# dim(x) 表明有8行2列
# 创建数组,8行2列3组,将x重复3组,保留行列名,组名:cop.1 cop,2 cop,3
x3 <- array(x, dim = c(dim(x),3),
dimnames = c(dimnames(x), list(C = paste0("cop.",1:3))))
# identical 判断两个对象是否精确相等,比==好用
# identity(x) 输出x的值
# x 8行2列; apply( x, 2, identity) 按列输出x 8行2列
identical(x, apply( x, 2, identity)) # 没区别
# x3 8行2列3组; apply(x3, 2:3, identity) 按列和组输出x3 8行2列3组
identical(x3, apply(x3, 2:3, identity)) # 没区别
##- function with extra args: 在apply中应用具有更多参数的复杂函数
# apply(X, MARGIN, FUN, ...) FUN后面的内容都是FUN的可选参数设置
# cave 函数 输出x的c1列的均值 和 c2列的均值
cave <- function(x, c1, c2) c(mean(x[c1]), mean(x[c2]))
# 按8个行输出两行计算结果: x1列的均值 和(x1列及x2列)的均值
# x1列的均值 就是x1列本身
apply(x, 1, cave, c1 = "x1", c2 = c("x1","x2"))
# 结果为 2行8列的向量组,第一行为x1列本身,第二行为(x1列及x2列)的均值
ma <- matrix(c(1:4, 1, 6:8), nrow = 2) # ma是按列排列的2行4列矩阵,byrow = FALSE
ma
apply(ma, 1, table) #--> a list of length 2 结果为2组的列表,按行统计频率
# 结果为ma矩阵按行统计频率
apply(ma, 1, stats::quantile) # 5 x n matrix with rownames 结果为带行名的向量组(原文说是矩阵,看起来是矩阵,实际上是向量组)
# stats::quantile 默认给出seq(0, 1, 0.25)概率的5个常规分位数,分配到ma的每行计算中
# ma矩阵2行4列,按行统计,结果共有2列;5个分位数,结果共有5行
# apply(ma, 1, FUN) 函数有几个指标,按行计算,结果就有几行,按列计算,结果就有几列
# 有点绕,梳理一下,本子上画一画就发现,有点形似矩阵的乘法
stopifnot(dim(ma) == dim(apply(ma, 1:2, sum))) # stopifnot没有报错,说明这俩维数相等
# dim(ma) 2行4列
# apply(ma, 1:2, sum) 结果和ma一样,identical(ma,apply(ma, 1:2, sum))结果为TRUE,这是我很困惑的地方,难道矩阵分别按行按列相加之后,和原矩阵一致?算一算,不一致啊,谁来告诉我这是咋回事?
## Example with different lengths for each call 每次调用不同长度的
# 创建数组,共24个元素,2行3列4组(dim = c(2,3,4))
z <- array(1:24, dim = 2:4)
# 一边调用apply一边编写一个函数
# 这个函数计算最大值的序列长度
zseq <- apply(z, 1:2, function(x) seq_len(max(x))) # 分别按行列计算最大值的序列长度
zseq ## a 2 x 3 matrix 结果是2行3列的矩阵,str显示其由6组整数序列组成的列表
# 结果表明最大值都出现在最后1组
typeof(zseq) ## list 与str的结果一致,确实是列表
dim(zseq) ## 2 3 但其维数是2行3列
zseq[1,] # 展示第一行!第一行是Integer,19 Integer,21 Integer,23 三组序列!
apply(z, 3, function(x) seq_len(max(x))) # 按组计算最大值的序列长度,z为2行3列4组的数组
# 结果是4组的列表
# a list without a dim attribute 结果没有维数属性,这是啥意思?我不是做出来4组了吗,但是结果如下:
==============================
[[1]]
[1] 1 2 3 4 5 6
[[2]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12
[[3]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[[4]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
> str(apply(z, 3, function(x) seq_len(max(x))))
List of 4
$ : int [1:6] 1 2 3 4 5 6
$ : int [1:12] 1 2 3 4 5 6 7 8 9 10 ...
$ : int [1:18] 1 2 3 4 5 6 7 8 9 10 ...
$ : int [1:24] 1 2 3 4 5 6 7 8 9 10 ...
=====================================
#emmm,看不懂这个function(x) seq_len(max(x))到底算了个啥?谁能赐教吗?谢谢!
这部分代码翻译自R帮助文档