2020-05-25 apply函数族

2020-05-25  本文已影响0人  TaosPlanet

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

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" 
上一篇下一篇

猜你喜欢

热点阅读