purrr包还提供了其他一些抽象表示for循环的函数,这些函数的使用频率比map()函数少,但还是有必要知道一下,以便遇到相似问题的时候可以有查找问题的方向。
判定函数
所谓判定函数(predicate functions),就是返回值是逻辑值的函数。一类for循环函数是基于判定函数工作的,包括:
1)keep()、discard()、compact(),功能分别是保留或丢弃vector或list满足某种条件(由判定函数决定)的元素、删除vector或list中的所有空元素(即NULL,注意NA、NaN等不是空元素)。
keep(.x, .p, ...)
discard(.x, .p, ...)
compact(.x, .p = identity)
.x : vector或list
.p : 判定函数,仅判定函数返回值为TRUE的元素被keep或discard
...:其他传递给.f的参数
> keep(1:10,~.>5)
[1] 6 7 8 9 10
> discard(1:10,~.>5)
[1] 1 2 3 4 5
> compact(rep(c(1,2,NULL),4))
[1] 1 2 1 2 1 2 1 2
2)every()、some()、none(),功能分别是list或atomic vector中的每一个元素、一些元素或没有一个元素满足判定条件吗?返回值是长度为1的逻辑向量。
every(.x, .p, ...)
some(.x, .p, ...)
none(.x, .p, ...)
.x : list 或atomic vector
.p :判定函数
> every(1:10,~.>5)
[1] FALSE
> some(1:10,~.>5)
[1] TRUE
> none(1:10,~.>5)
[1] FALSE
3)detect()、detect_index(),功能分别是返回第一个匹配的元素、index。
detect(.x, .f, ..., .dir = c("forward", "backward"), .right = NULL,
.default = NULL)
detect_index(.x, .f, ..., .dir = c("forward", "backward"), .right = NULL)
正如所看到的参数,可以设置匹配方向,默认是:forward,即从.x的开始向末尾匹配;
.right参数被废弃了,用.dir代替
.default:当没有匹配到结果时,默认返回NULL,可以设置为别的。
4)head_while()、tail_while(),功能分别是找到所有满足判定条件的头和尾。
head_while(.x, .p, ...)
tail_while(.x, .p, ...)
> head_while(1:10,~.>5)
integer(0)
> tail_while(1:10,~.>5)
[1] 6 7 8 9 10
reduce() 和accumulate()
reduce()函数用来通过反复应用一个能将双例转化为单例的函数,将复杂列表转换成简单列表。
reduce(.x, .f, ..., .init, .dir = c("forward", "backward"))
reduce2(.x, .y, .f, ..., .init)
.x:list或atomic vector
.f:对reduce(),.f应该是有两个原始输入的函数;对reduce2(),.f应该是有三个原始输入的函数
.init:不指定时,默认.x[[1]]作为初始值;指定时,使用指定值作为初始值
.dir:如果.f是类似+、c()等连接型的函数,对方向无要求,否则需指定方向,默认"forward"。
举个例子:
> x <- 1:3
> reduce(x,`+`)
[1] 6
初始值x[1],即1;最后简化为(1+2)+3=6
> reduce(x,`+`,.init=2)
[1] 8
我们可以用merge()函数合并两个数据框。如果有多个数据框同时需要合并,可以用reduce()来自动循环执行merge()。
> (birthtime <- data.frame(name=c("Zhangs","Lis","Wangw","Qianl"),birthtime=c("19900103","19900630","19891203","19920709")))
name birthtime
1 Zhangs 19900103
2 Lis 19900630
3 Wangw 19891203
4 Qianl 19920709
> (sex <- data.frame(name=c("Zhangs","Qianl","Wangw"),sex=c("male","female","male")))
name sex
1 Zhangs male
2 Qianl female
3 Wangw male
> (height<-data.frame(name=c("Qianl","Wangw","Lis"),height=c(162,178,158)))
name height
1 Qianl 162
2 Wangw 178
3 Lis 158
> reduce(list(birthtime,sex,height),merge,by="name",all=T)
name birthtime sex height
1 Lis 19900630 <NA> 158
2 Qianl 19920709 female 162
3 Wangw 19891203 male 178
4 Zhangs 19900103 male NA
相当于:
> (tmp1<-merge(birthtime,sex,by="name",all=T))
> merge(tmp1,height,by="name",all=T)
accumulate()会保留reduce()每次循环的结果:
accumulate(.x, .f, ..., .init, .dir = c("forward", "backward"))
accumulate2(.x, .y, .f, ..., .init)
> accumulate(list(birthtime,sex,height),merge,by="name",all=T)
# 初始值是birthtime
[[1]]
name birthtime
1 Zhangs 19900103
2 Lis 19900630
3 Wangw 19891203
4 Qianl 19920709
# 合并birthtime和sex
[[2]]
name birthtime sex
1 Lis 19900630 <NA>
2 Qianl 19920709 female
3 Wangw 19891203 male
4 Zhangs 19900103 male
# 合并[[2]]和height
[[3]]
name birthtime sex height
1 Lis 19900630 <NA> 158
2 Qianl 19920709 female 162
3 Wangw 19891203 male 178
4 Zhangs 19900103 male NA
# 累加
> accumulate(1:5,`+`)
[1] 1 3 6 10 15
> cumsum(1:5)
[1] 1 3 6 10 15
网友评论