前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >R:purrr包用于循环迭代

R:purrr包用于循环迭代

作者头像
生信菜鸟团
发布2020-07-16 10:50:43
1.6K0
发布2020-07-16 10:50:43
举报
文章被收录于专栏:生信菜鸟团

purrr中有多个迭代函数,可以用于快速解决循环迭代的问题,purrr中常用的迭代函数有map、map2、walk、reduce等等。

map

代码语言:javascript
复制
map(.x, .f, ...)

map函数接受一个向量、列表,对其每一个元素执行函数。

数据框其实是一种格式化表示的列表,所以也可以使用map迭代。

map函数默认返回列表。

代码语言:javascript
复制
iris %>% map(mean)
# $Sepal.Length
# [1] 5.843333
# 
# $Sepal.Width
# [1] 3.057333
# 
# $Petal.Length
# [1] 3.758
# 
# $Petal.Width
# [1] 1.199333
# 
# $Species
# [1] NA

如果返回值需要是一个数值向量,而不是列表,也可以使用map_dbl、map_chr、map_lgl等形式,代表分别返回数值、字符或者逻辑值。

代码语言:javascript
复制
iris %>% map_dbl(mean)
#Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
#   5.843333     3.057333     3.758000     1.199333           NA

可以看到Species不是数值是无法求mean,那么此时可以使用map_if或者map_at跳过Species。

注意:此时的跳过是指的不对跳过的列执行函数mean,直接将其内容返回。

代码语言:javascript
复制
iris %>% map_at(1:4, mean) # 只对前四列计算mean

对于map_if而言可以使用.else参数控制跳过的列的执行函数。

代码语言:javascript
复制
iris %>% map_if(is.numeric, mean, .else = ~"不适用")
#$Sepal.Length
#[1] 5.843333
#$Sepal.Width
#[1] 3.057333
#$Petal.Length
#[1] 3.758
#$Petal.Width
#[1] 1.199333
#$Species
#[1] "不适用"

如果还有其他参数,放到函数后边即可:

代码语言:javascript
复制
iris %>% map_dbl(mean, na.omit=T)

.f有三个快捷方式:公式、字符及数字。

代码语言:javascript
复制
# 公式:用于简化R的匿名函数格式
# 例如如下两种方式是等价的
iris %>% map(function(x) mean(x, na.omit=T))
iris %>% map(~mean(., na.omit=T))

# 字符:用于快速提取内容
# 例如如下两种方式是等价的
iris %>% dplyr::select(-Species) %>% map(summary) %>%map_dbl(~.["Median"])
iris %>% dplyr::select(-Species) %>% map(summary) %>%map_dbl("Median")

# 数字:也是用于快速提取内容,按位置取值
iris %>% dplyr::select(-Species) %>% map(summary) %>% map_dbl(3)

map2

代码语言:javascript
复制
map2(.x, .y, .f, ...)

map2可以对两个向量、列表同时进行迭代。

代码语言:javascript
复制
x <- 1:3
y <- list(4,5,6)
map2(x,y,rnorm,n=5)
# [[1]]
# [1] -1.583531618 -4.480785670  0.008262269  0.452103825  4.257641158
# 
# [[2]]
# [1]  2.835951 -2.392248  2.874423 -2.714616  9.362894
# 
# [[3]]
# [1] -6.5547160 -4.3619104 -5.5202971 -0.1914993  2.2787720

可以同时对列表的名称和内容进行迭代,先将列表使用enframe转换为一个tibble:

代码语言:javascript
复制
x <- 1:3
y <- list(4,5,6)
paras <- list(mean=x, sd=y)
paras <- tibble::enframe(paras)
## A tibble: 2 x 2
#  name  value     
#  <chr> <list>    
#1 mean  <int [3]> 
#2 sd    <list [3]>
map2(paras$name, paras$value, ~stringr::str_c(.x, .y[[1]], collapse=""))
#[[1]]
#[1] "mean1"
#
#[[2]]
#[1] "sd4"

map2在使用管道时,可以使用%$%:

代码语言:javascript
复制
library(magrittr)
list(mean=1:3, sd=4:6) %>% 
  tibble::enframe() %$% 
  map2(name, value, ~stringr::str_c(.x, .y[[1]], collapse=""))
#[[1]]
#[1] "mean1"
#
#[[2]]
#[1] "sd4"

pmap

代码语言:javascript
复制
pmap(.l, .f, ...)

pmap代表对多个列表进行迭代,将多个列表包装为一个列表传给.f可。

代码语言:javascript
复制
x <- 1:3
y <- list(4,5,6)
z <- list(1,2,3)
pmap(list(mean=x, sd=y, n=z), rnorm)
#相当于rnorm(mean=1, sd=4, n=1)、rnorm(mean=2, sd=5, n=2)、rnorm(mean=3, sd=6, n=3)

#[[1]]
#[1] 6.224277
#
#[[2]]
#[1] 12.32054 10.57245
#
#[[3]]
#[1] 6.593741 1.389408 3.541097

invoke_map

代码语言:javascript
复制
invoke_map(.f, .x = NULL, ..., .env = NULL)

invoke_map用于函数(.f参数)也不固定的情况。

代码语言:javascript
复制
x <- list(n = 3)
y <- list(n = 5, lambda = 10)
z <- list(n = 3, mean = -3, sd = 10)
fun <- c("runif", "rpois", "rnorm")
invoke_map(fun, list(x,y,z))
#相当于runif(n=3)、rpois(n=5, lambda=10)、rnorm(n=3, mean=-3, sd=10)

#[[1]]
#[1] 0.09462862 0.54110640 0.87654702
#
#[[2]]
#[1] 10  6  5  8  9
#
#[[3]]
#[1] -20.92633 -14.80254 -16.16675

walk

除了上述的map系列函数,还有一批形式类似的walk函数,如walk、walk2、pwalk等等,他们用于一些不需要返回值的操作,如绘图和读写文件。

如果此时使用map系列函数,那么就会返回一个值为NULL的列表。

代码语言:javascript
复制
df <- data.frame(plot1 = rnorm(5,1,1), 
                 plot2 = rnorm(5,2,3), 
                 plot3 = rnorm(5,4,5))
map(df, plot) #除了绘制三张散点图外,还会返回一个值为NULL的列表
#$plot1
#NULL
#$plot2
#NULL
#$plot3
#NULL
walk(df, plot) #只绘图,没有返回值

reduce

reduce是一个特殊的迭代函数,它执行一种“积累”的操作,如累加、累乘:

代码语言:javascript
复制
reduce(1:100, `+`)
#[1] 5050
reduce(1:5, `*`)
#[1] 120

有些时候,reduce是很方便的,比如可以使用它计算数据框的最大值和最小值:

代码语言:javascript
复制
reduce(iris, min) #0.1
reduce(iris, max) #7.9

和reduce类似的一个函数是accumulate,它会将中间每一个迭代过程记录下来:

代码语言:javascript
复制
head(iris) %>% accumulate(min)

#$Sepal.Length
#[1] 5.1 4.9 4.7 4.6 5.0 5.4
#$Sepal.Width
#[1] 3
#$Petal.Length
#[1] 1.3
#$Petal.Width
#[1] 0.2
#$Species
#[1] 0.2
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 生信菜鸟团 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • map
  • map2
  • pmap
  • invoke_map
  • walk
  • reduce
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档