本周主要介绍了5个apply函数以及split的用法:
-lapply
-sapply
-apply
-tapply
-mapply
-split
输入一个列表,通过循环后输出一个列表。原列表的名称会被保留。
str(lapply)
## function (X, FUN, ...)
x 表示输入一个列表
FUN 表示输入一个循环的函数
... 表示对各个元素作用的参数
#这里对list里的每个元素:a和b都进行了取均值操作。
x<-list(a=1:5, b=rnorm(10))
lapply(x,mean)
## $a
## [1] 3
##
## $b
## [1] 0.3408504
使用runif(n)函数可以生成n个[0,1]均匀分布的数字
#这里对list里的每个元素(矩阵):a和b都进行了自定义的函数的操作(取第一列)。从中我们发现,对于loop function而言,可以自定义函数来丰富用途。
x<-list(a=matrix(1:4, nrow = 2, ncol = 2),b=matrix(1:6, nrow = 3, ncol = 2))
x
## $a
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $b
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
lapply(x,function(fc) fc[,1])
## $a
## [1] 1 2
##
## $b
## [1] 1 2 3
简化版的lapply,输出的类型不是列表。
| lapply输出 | sapply的输出 |
|---|---|
| 列表每个列只有一个元素 | 返回向量 |
| 列表每个列有多个元素 | 返回矩阵 |
#对于同一个列表,lapply和sapply的输出结果的可视化效果是不同的。
x<-list(a=1:5, b=rnorm(10))
lapply(x,mean)
## $a
## [1] 3
##
## $b
## [1] 0.1204788
sapply(x,mean)
## a b
## 3.0000000 0.1204788
作用于数组Array
str(apply)
## function (X, MARGIN, FUN, ...)
x 表示一个数组活矩阵
margin 表示需要被保留的行/列(用向量表示)
fun 表示循环的函数
... 表示循环的其他参数变量
#生成一个20*10的矩阵,返回行/列的均值(1表示行,2表示列)
x<-matrix(rnorm(200),20,10)
apply(x,2,mean)
## [1] -0.06188239 -0.03269108 0.58289229 -0.36218301 -0.03836910
## [6] -0.02537240 0.46658706 -0.17852356 -0.15340693 -0.07022349
apply(x,1,mean)
## [1] -0.29701778 -0.14006171 -0.43917206 0.29984874 -0.06061634
## [6] 0.80750995 -0.11379374 0.72217569 0.03984844 0.18639416
## [11] -0.30038746 0.38263315 -0.22407108 0.26671167 0.26499031
## [16] -0.29352288 -0.15593159 0.21355030 -0.50629262 -0.39914037
通常情况下,矩阵的行列的均值及和可以用以下函数来代替:
rowSums=apply(x,1,sum)
rowMeans=apply(x,1,mean)
colSums=apply(x,2,sum)
colMeans=apply(x,2,mean)
再看一个例子:
#这里返回的是x矩阵列元素的25%和75%分位点
x<-matrix(rnorm(200),20,10)
apply(x,2,quantile,probs=c(0.25,0.75))
## [,1] [,2] [,3] [,4] [,5] [,6]
## 25% -0.9424618 -0.9698283 -0.5705675 -0.1404938 -0.2693255 -0.6847354
## 75% 0.3759125 0.5900999 0.4542125 1.1869608 1.3508776 0.5925187
## [,7] [,8] [,9] [,10]
## 25% -0.3615953 -0.4143352 -0.6975408 -1.12497462
## 75% 0.5297599 0.6186339 0.4515598 0.09709502
m表示muti的意思,将函数依次应用每一个参数的每一个元素上。
str(mapply)
## function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)
fun 作用的函数
MoreArgs 函数FUN的参数列表
simplify 输出的结果为列表还是简化输出形式
use.names 是否保留名称
#在标准差为2的情况下,在均值为1,2,...,5的正态分布函数中,分别取1个2个...5个数。
noise<-function(n,mean,sd){rnorm(n,mean,sd)}
mapply(noise,1:5,1:5,2)
## [[1]]
## [1] -0.7426653
##
## [[2]]
## [1] 0.8913268 4.1345896
##
## [[3]]
## [1] 3.3386378 5.2706587 0.2658873
##
## [[4]]
## [1] 6.728787 5.849955 6.162188 8.584332
##
## [[5]]
## [1] 5.524032 6.096981 5.827205 5.791165 4.689238
#等同于
list(noise(1, 1, 2), noise(2, 2, 2),
noise(3, 3, 2), noise(4, 4, 2),
noise(5, 5, 2))
## [[1]]
## [1] 0.996337
##
## [[2]]
## [1] 1.473952 4.966508
##
## [[3]]
## [1] 2.974292 1.283822 6.818675
##
## [[4]]
## [1] 2.192741 7.413558 7.487915 4.678593
##
## [[5]]
## [1] 4.411867 3.475751 1.542282 3.612318 5.994316
作用于一个向量或者一个子集上的循环函数。
str(tapply)
## function (X, INDEX, FUN = NULL, ..., default = NA, simplify = TRUE)
x 向量
INDEX 因子列表(分类的依据)
FUN 作用的函数
... 其他作用的参数
simplify 简化输出(默认TRUE)
#将求每个因子分组下的均值,x代表向量,f因子表示分组的依据。
x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
tapply(x, f, mean)
## 1 2 3
## -0.1252369 0.4973668 0.8715860
split不是一个循环函数,但是常和其他的循环函数放在一起使用。
str(split)
## function (x, f, drop = FALSE, ...)
x 代表向量/列表/数据帧中的一种类型
f 因子
drop 是否不输出空的因子所在的分组(默认FALSE,输出)
#与tapply相似,只是用split函数将x向量按照f的因子分组
x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
split(x, f)
## $`1`
## [1] -0.6887626 1.0373056 -0.3518526 -1.3829744 1.4510218 0.5454222
## [7] 0.1869283 1.4108691 0.2388184 -0.4149929
##
## $`2`
## [1] 0.6257186 0.4020127 0.7690439 0.4558853 0.8105415 0.3457467 0.5945598
## [8] 0.7318233 0.9643959 0.3295082
##
## $`3`
## [1] 1.07755769 1.32347784 -0.35257708 1.50591536 2.42150231
## [6] -0.75350222 0.80560197 1.88319525 -0.07647322 1.18882857
#split函数与lapply函数的结合使用:
lapply(split(x, f), mean)
## $`1`
## [1] 0.2031783
##
## $`2`
## [1] 0.6029236
##
## $`3`
## [1] 0.9023526
#采用R自带的空气质量数据集
library(datasets)
#按照月份(因子)进行分割(成一个列表形式的数据结构)
s <- split(airquality, airquality$Month)
#用lapply求列均值的结果返回时一个列表
lapply(s, function(x) colMeans(x[, c("Ozone", "Solar.R", "Wind")]))
## $`5`
## Ozone Solar.R Wind
## NA NA 11.62258
##
## $`6`
## Ozone Solar.R Wind
## NA 190.16667 10.26667
##
## $`7`
## Ozone Solar.R Wind
## NA 216.483871 8.941935
##
## $`8`
## Ozone Solar.R Wind
## NA NA 8.793548
##
## $`9`
## Ozone Solar.R Wind
## NA 167.4333 10.1800
#但是用sapply返回的就是数据帧
sapply(s, function(x) colMeans(x[, c("Ozone", "Solar.R", "Wind")]))
## 5 6 7 8 9
## Ozone NA NA NA NA NA
## Solar.R NA 190.16667 216.483871 NA 167.4333
## Wind 11.62258 10.26667 8.941935 8.793548 10.1800
#将缺失值剔除后:
sapply(s, function(x) colMeans(x[, c("Ozone", "Solar.R", "Wind")],na.rm = TRUE))
## 5 6 7 8 9
## Ozone 23.61538 29.44444 59.115385 59.961538 31.44828
## Solar.R 181.29630 190.16667 216.483871 171.857143 167.43333
## Wind 11.62258 10.26667 8.941935 8.793548 10.18000