美文网首页
2020-05-25 apply函数族

2020-05-25 apply函数族

作者: TaosPlanet | 来源:发表于2020-05-25 22:07 被阅读0次

    其实也没必要记住这么多,不会用了查就行

    lapply
    |
    |-> 简化版: sapply
    | | -> 可设置返回值模板: vapply
    | |-> 多变量版: mapply
    |
    |-> 递归版: rapply

    apply

    1. 3个参数,(data,margin,FUN)

    2. 应用在matrix或array上

    sweep

    常常和apply一起用,sweep函数和apply函数相似,但是sweep主要用于array的计算,而apply更多的是矩阵和data.frame计算。

    mean.att <- apply(attitude, 2, mean)
    sweep(attitude, 2, mean.att, FUN = "-") %>% head()
    

    tapply和aggregate

    tapply函数很有用,tapply的功能就是把数据按照某种分组,在每个组内进行某个运算。这个aggregate函数很像。我觉得还是aggregate好用。

    > aggregate(mtcars,by=list(mtcars$cyl,mtcars$gear),FUN=mean)
    ...略
    
    > aggregate(mtcars,by=list(mtcars$gear),FUN=mean)
      Group.1      mpg      cyl     disp       hp     drat       wt   qsec        vs        am
    1       3 16.10667 7.466667 326.3000 176.1333 3.132667 3.892600 17.692 0.2000000 0.0000000
    2       4 24.53333 4.666667 123.0167  89.5000 4.043333 2.616667 18.965 0.8333333 0.6666667
    3       5 21.38000 6.000000 202.4800 195.6000 3.916000 2.632600 15.640 0.2000000 1.0000000
      gear     carb
    1    3 2.666667
    2    4 2.333333
    3    5 4.400000
    
    > aggregate(mtcars$qsec,by=list(mtcars$gear),FUN=mean)
      Group.1      x
    1       3 17.692
    2       4 18.965
    3       5 15.640
    
    
    > aggregate(cbind(mpg,hp) ~ cyl+gear, FUN=mean)
      cyl gear    mpg       hp
    1   4    3 21.500  97.0000
    2   6    3 19.750 107.5000
    3   8    3 15.050 194.1667
    4   4    4 26.925  76.0000
    5   6    4 19.750 116.5000
    6   4    5 28.200 102.0000
    7   6    5 19.700 175.0000
    8   8    5 15.400 299.5000
    
    > tapply(mtcars$qsec,mtcars$gear, mean)
         3      4      5 
    17.692 18.965 15.640 
    

    还可以实现crosstable功能,这个很好用

    > df <- data.frame(year=kronecker(2001:2003, rep(1,4)), 
                      loc=c('beijing','beijing','shanghai','shanghai'), 
                      type=rep(c('A','B'),6), sale=rep(1:12))
    > tapply(df$sale, df[,c('year','loc')], sum)
    
          loc
    year   beijing shanghai
      2001       3        7
      2002      11       15
      2003      19       23
    
    # 类似的aggregate就麻烦一些
    > aggregate(df$sale, by = list(df$year,df$loc),FUN= sum) %>% 
    +     reshape2::dcast(Group.1~Group.2)
    
      Group.1 beijing shanghai
    1    2001       3        7
    2    2002      11       15
    3    2003      19       23
    
    

    sapply和lapply

    1. 都只有两个参数,第一个参数是输入数据,第二个是函数。

    2. 都应用在一个vector或list上

    3. sapply返回的是一个vector,但是lapply返回的是一个list。其实sapply可以理解成lapply的简化版,s就是simplify的意思。

    其它:为了让sapply返回array或matrix,simplify参数很好用。

    sapply(1:5,function(x) matrix(x,2,2), simplify = "array")
    

    这两个sapply/lapply 常和unlist(),matrix(),as.dataframe(),函数一起使用

    mapply

    1. 多变量版的sapply,很好用,m就是multi的意思。
    2. 返回值是vector或matrix
    image

    下面这段代码值得一看

    Alco <- data.frame(AlcoholDrunk = c( "YES", "YES", "NO",  "YES", "YES", "YES", NA, "YES", "YES", "YES", "YES", "YES", "YES", "NO",  "NO",  "NO",  "NO", "YES"), 
                       AmountDrunk = c(3.0, 1.0,  NA ,3.0,  NA, 0.0,  NA, 0.0,  NA, 1.7,  NA,  NA, 0.0,  NA,  NA,  NA,  NA, 2.0))
    
    #这里AlcoholDrunk变量有三种类型的值,“YES”,表示有饮酒史;“NO”, 表示无饮酒史;NA, 表示数据不可获取。
    # alcohol函数实现的功能是:如果AlcoholDrunk是NA,直接返回NA,如果是NO,返回NO;否则返回AmountDrunk的数值。
    alcohol <- function(texVal, numVal){
      if(is.na(texVal)) {return("NA")}
      else if(texVal == "NO"){return("NO")}
      else if(is.na(numVal)){return("amount Unknown")}
      else {return(numVal)}
    }
    
    mapply(alcohol, Alco$AlcoholDrunk, Alco$AmountDrunk)
    

    replicate

    另外还有一个非常有用的函数replicate(),它可以将某个函数重复运行N次,常常用来生成较复杂的随机数。下面的例子即先建立一个函数,模拟扔两个骰子的点数之和,然后重复运行1000次。

    # 定义一个game函数
    game <- function() {
    n <- sample(1:6,2,replace=T) #这个sample()函数也挺有意思的,我想replicate()应该经常会和sample()连用
    return(sum(n))
    }
    
    replicate(n=1000,game())  #将game()函数重复运行1000次。
    

    rapply

    这个好像也非常有用

    rapply(list, FUN, classes="ANY", deflt=NULL, how=c("unlist", "replace", "list"), ...)
    

    rapply是递归版的lappy。基本原理是对list作遍历,如果其中有的元素仍然是list,则继续遍历;对于每个非list类型的元素,如果其类型是classes参数指定的类型之一,则调用FUN。classes="ANY"表示匹配所有类型。

    how参数用来指定操作方式,有三种:

    a. "replace" 直接用调用FUN后的结果替换原list中原来的元素
    b. "list" 新建一个list,元素类型在classes中的,调用FUN;不在classes中的类型,使用deflt。会保留原始list的结构。
    c. "unlist" 相当于对"list"模式下的结果调用unlist(recursive=TRUE)

    看完下面的例子你就明白了

    > lst <- list(a=list(aa=c(1:5), ab=c(0.1,0.2,0.25,0.3,0.33)),  #a list里两个元素
    +             b=list(ba=c(1:10)),   #b list里一个元素
    +             c=c('ha','m','k'))  #c 不是一个list; a,b,c共同构成了lst list
    > lst
    $a
    $a$aa
    [1] 1 2 3 4 5
    
    $a$ab
    [1] 0.10 0.20 0.25 0.30 0.33
    
    
    $b
    $b$ba
     [1]  1  2  3  4  5  6  7  8  9 10
    
    
    $c
    [1] "ha" "m"  "k" 
    
    > rapply(lst, sum, how='list',classes = 'numeric')
    $a
    $a$aa
    NULL
    
    $a$ab
    [1] 1.18
    
    
    $b
    $b$ba
    NULL
    
    
    $c
    NULL
    
    > rapply(lst, sum, how='unlist',classes = c('integer'))
    a.aa b.ba 
      15   55 
    > rapply(lst, sum, how='unlist',classes = c('integer','numeric'))
     a.aa  a.ab  b.ba 
    15.00  1.18 55.00 
    > rapply(lst, sum, how='unlist',classes = c('integer','numeric'),deflt="This is deflt")
               a.aa            a.ab            b.ba               c 
               "15"          "1.18"            "55" "This is deflt" 
    > rapply(lst, nchar, how='unlist',classes = "character", deflt="DEFLT")
       a.aa    a.ab    b.ba      c1      c2      c3 
    "DEFLT" "DEFLT" "DEFLT"     "2"     "1"     "1" 
    

    相关文章

      网友评论

          本文标题:2020-05-25 apply函数族

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