美文网首页
R 中for 循环替代函数:apply、Map及purrr::m

R 中for 循环替代函数:apply、Map及purrr::m

作者: 生信小白2018 | 来源:发表于2019-08-06 20:41 被阅读0次

R 中apply函数、Map函数及purrr包的map函数

apply()函数算是R语言里面很基础的一个函数,同时还有sapply()、lapply()、tapply()函数精简了apply()的用法。
apply可以起到很好的替代冗余的for循环的作用
R语言的循环操作for和while,都是基于R语言本身来实现的,而向量操作是基于底层的C语言函数实现的,
apply()可以面向数据框、列表、向量等,同时任何函数都可以传递给apply()函数。

apply()函数的用法如下:

apply(X, MARGIN, FUN)
Here:
-x: 一个数组或者矩阵
-MARGIN: 两种数值1或者2决定对哪一个维度进行函数计算
-MARGIN=1`: 操作基于行
-MARGIN=2`: 操作基于列
-MARGIN=c(1,2)`: 对行和列都进行操作
-FUN: 使用哪种操作,内置的函数有mean(平均值)、medium(中位数)、sum(求和)、min(最小值)、max(最大值),当然还包括广大的用户自定义函数
> m1 <- matrix(C<-(1:10),nrow=5, ncol=6)
> m1
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    6    1    6    1    6
[2,]    2    7    2    7    2    7
[3,]    3    8    3    8    3    8
[4,]    4    9    4    9    4    9
[5,]    5   10    5   10    5   10
> a_m1 <- apply(m1, 2, sum)
> a_m1
[1] 15 40 15 40 15 40

lapply()函数

lapply()函数中多出来的l代表的是list,所以lapply()和apply()的区别在于输出的格式,lapply()的输出是一个列表(list),所以lapply()函数不需要MARGIN参数:

lapply(X, FUN)
Arguments:
-X: 一个向量或者是一个对象
-FUN: 对X里面每个元素进行操作的函数

一个很简单的示例操作就是把一个字符向量里面的字符转成小写:

movies <- c("SPYDERMAN","BATMAN","VERTIGO","CHINATOWN")
class(movies)
[1] "character"
> movies_lower <-lapply(movies, tolower)
> str(movies_lower)
List of 4
 $ : chr "spyderman"
 $ : chr "batman"
 $ : chr "vertigo"
 $ : chr "chinatown"

我们可以看到,输出的内容是以list形式给出的,为了方便,我们可以使用unlist()函数进行整合:

movies_lower <-unlist(lapply(movies,tolower))
str(movies_lower)
chr [1:4] "spyderman" "batman" "vertigo" "chinatown"

sapply()函数
sapply()函数做的事情和lapply()一样,可以理解为是一个简化的lapply,返回的是一个向量(vector)使得对解读更加友好,其使用方法和lapply一样,不过多了两个参数: simplify&use.NAMEs,simplify = T可以将输出结果数组化,如果设置为false,sapply()函数就和lapply()函数没有差别了,use.NAMEs = T可以设置字符串为字符名。

tapply()函数

这里拓展一个函数:tapply(),它可以对一个向量里面进行分组统计操作。
是不是想起了dplyr包里面的group_by函数 + summarize()函数。

其参数为:

tapply(X, INDEX, FUN = NULL)
Arguments:
-X: 一个对象,一般都是向量
-INDEX: 一个包含分类因子的列表(list)
-FUN: 对X里面每个元素进行操作的函数
拿鸢尾花数据(iris)举例,其有三个品种:Setosa, Versicolor,  Virginica,以下代码可以计算三个品种平均宽度:
data(iris)
head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
> tapply(iris$Sepal.Width, iris$Species, median)
    setosa versicolor  virginica 
       3.4        2.8        3.0 


使用dplyr包可以实现同样的目的:

iris %>% group_by(Species) %>% summarise(mean(Sepal.Width))
# A tibble: 3 x 2
  Species    `mean(Sepal.Width)`
  <fct>                    <dbl>
1 setosa                    3.43
2 versicolor                2.77
3 virginica                 2.97

purrr::map

map语法:map(.x, .f, ...),语法与apply接近
.x :数据集
.f映射函数
map(iris[, -5],mean)  ##求iris数据集中,数值型变量的均值
iris[, -5]
iris[-1]
head(iris)
unlist(map(iris[, -5],mean))
#同样的效果,可以通过以下 2种方式实现

apply(iris[, -5], 2, mean)
summarise_all(iris[, -5],mean)

例子

rnorm函数
语法:rnorm(n, mean = 0, sd = 1) #有n、mean、sd 3个变量
rnorm(6,7,1)

x <- list( 1, 10, 100)
y <- list( 1, 2, 3)
z <- list( 5, 5, 5)

#以下用 3种方式,实现rnorm效果
1:map方式

set.seed( 123)
1:3%>%map(~rnorm(z [[.]],x [[.]], y [[.]]))

2:map2方式

set.seed( 123)
map2(x,y,rnorm, n = 5)

3:pmap方式

set.seed( 123)
pmap(list(z,x,y),rnorm)

参考

https://www.jianshu.com/p/8e04245bfe6d
http://www.sohu.com/a/309277835_165070

相关文章

网友评论

      本文标题:R 中for 循环替代函数:apply、Map及purrr::m

      本文链接:https://www.haomeiwen.com/subject/tgawdctx.html