美文网首页
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