purrr 包之 map 系列函数
purrr 包是 Hadley Wickham 大神编写的高级函数编程语言包,相对于 apply 家族的函数操作,具有更快更好的使用效果,能够更好的提高写代码的效率。里面包含了很多函数,今天来介绍一下 map 的系列函数, map 函数能够对向量或列表使用函数进行迭代操作。
map()函数

map 函数对 .x(向量或列表)的每个元素执行 .f(函数)操作,并返回一个 list,…为执行函数的其它参数。。以下是不同类型的 map 函数返回不同类型的结果:
| function | returns | 返回类型 |
|---|---|---|
| map | list | 列表 |
| map_chr | character vector | 字符型 |
| map_dbl | double (numeric) vector | 双精度 |
| map_df | data frame | 按合并成表格 |
| map_dfc | data frame (column bind) | 按列合并成表格 |
| map_dfr | data frame (row bind) | 按行合并成表格 |
| map_int | integer vector | 整数型 |
| map_lgl | logical vector | 逻辑型 |
使用:
# 加载R包library(dplyr)library(purrr)library(datasets)# 加载测试数据data("mtcars")# 查看数据head(mtcars)mpg cyl disp hp drat wt qsec vs am gear carbMazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4...
对每列求和:
mtcars %>% map(.,mean)$mpg[1] 20.09062$cyl[1] 6.1875$disp[1] 230.7219...
返回结果为字符型:
mtcars %>% map_chr(.,mean)mpg cyl disp hp drat wt qsec"20.090625" "6.187500" "230.721875" "146.687500" "3.596563" "3.217250" "17.848750"vs am gear carb"0.437500" "0.406250" "3.687500" "2.812500"
返回结果为双精度型:
mtcars %>% map_dbl(.,mean)mpg cyl disp hp drat wt qsec vs am20.090625 6.187500 230.721875 146.687500 3.596563 3.217250 17.848750 0.437500 0.406250gear carb3.687500 2.812500
返回结果为表格按列合并:
mtcars %>% map_dfc(.,mean)# A tibble: 1 x 11mpg cyl disp hp drat wt qsec vs am gear carb<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>1 20.1 6.19 231. 147. 3.60 3.22 17.8 0.438 0.406 3.69 2.81
加入自定义函数使用:
lst <- list(a = c(1:5),b = c(2:6))# 定义加1函数myfun <- function(x){x + 1}# 对每个list元素加1,结果合并成表格map_df(lst,myfun)# A tibble: 5 x 2a b<dbl> <dbl>1 2 32 3 43 4 54 5 65 6 7
多参数,对每个元素取log以2为底数:
lst <- list(a = c(1:5),b = c(2:6))map(lst,log,base = 2)$a[1] 0.000000 1.000000 1.584963 2.000000 2.321928$b[1] 1.000000 1.584963 2.000000 2.321928 2.584963
map2()函数

map2 函数对两个向量或列表配对的元素进行 .f(函数)操作,元素长度必须一样,…为执行函数的其它参数。。
使用:
对 mpg 和 disp 两列每个对应元素求和:
map2_dbl(mtcars$mpg,mtcars$disp,sum)[1] 181.0 181.0 130.8 279.4 378.7 243.1 374.3 171.1 163.6 186.8 185.4 292.2 293.1 291.0 482.4 470.4[17] 454.7 111.1 106.1 105.0 141.6 333.5 319.2 363.3 419.2 106.3 146.3 125.5 366.8 164.7 316.0 142.4
使用自定义函数:
x = c(1:4) ; x[1] 1 2 3 4y = c(2:5) ; y[1] 2 3 4 5# 定义函数myfun <- function(x,y){x*x + y}# 计算,返回双精度map2_dbl(x,y,myfun)[1] 3 7 13 21
假如两个向量或列表长度不等:
x = c(1:3) ; x[1] 1 2 3y = c(2:5) ; y[1] 2 3 4 5myfun <- function(x,y){x*x + y}map2_dbl(x,y,myfun)错误: Mapped vectors must have consistent lengths:* `.x` has length 3* `.y` has length 4
对两个列表操作:
# lst1x = c(1:4)y = c(2:5)lst1 <- list(x,y) ; lst1[[1]][1] 1 2 3 4[[2]][1] 2 3 4 5# lst2a = c(-1:-4) ; a[1] -1 -2 -3 -4b = c(-2:-5) ; b[1] -2 -3 -4 -5lst2 <- list(a,b) ; lst2[[1]][1] -1 -2 -3 -4[[2]][1] -2 -3 -4 -5# 定义两个列表每个对应元素相加函数myfun <- function(x,y){x + y}# 计算map2(lst1,lst2,myfun)[[1]][1] 0 0 0 0[[2]][1] 0 0 0 0
多参数,自定义多参数:
myfun <- function(x,y,n = 0){x + y + n}map2(lst1,lst2,myfun,n=1)[[1]][1] 1 1 1 1[[2]][1] 1 1 1 1
对于 map2 函数,返回结果的类型和 map 相似,只需要 map2_* 跟上相应类型即可:
pmap()函数

pmap 函数可对多个向量或列表对应的元素进行 .f(函数)操作,…为执行函数的其它参数。
使用:
x <- list(1, 1, 1)y <- list(10, 20, 30)z <- list(100, 200, 300)pmap_dbl(list(x, y, z), sum)[1] 111 221 331
计算x和y的和,再与z的乘积,按位置迭代:
pmap_dbl(list(x, y, z), function(first, second, third) {(first + third) * second})[1] 1010 4020 9030
计算x和z的和,再与y的乘积,按名字迭代:
l <- list(a = x, b = y, c = z) ; l$a$a[[1]][1] 1$a[[2]][1] 1$a[[3]][1] 1...pmap_dbl(l, function(c, b, a) {(a + c) * b})[1] 1010 4020 9030
计算mtcars前两列和与后两列和的乘积:
lst <- list(mtcars[,1],mtcars[,2],mtcars[,3],mtcars[,4])pmap_dbl(lst,function(a,b,c,d){(a + b)*(c + d)})[1] 7290.00 7290.00 5386.80 10083.20 14284.50 7953.00 13491.50 5927.08 6319.44[10] 7323.12 6916.28 11121.52 11531.74 10574.56 12456.80 12420.00 15209.00 5267.08[19] 4392.88 5158.19 5536.05 10998.00 10532.80 12673.50 15640.00 4538.50 6339.00[28] 7158.64 14637.00 8224.00 14628.00 5842.00
invoke_map()函数

invoke_map函数可以对每个list的元素执行多个不同的函数,…为执行函数的其它参数。
使用:
对x使用两个函数,一个加1,一个减1
lst <- list(fun1 <- function(x){x+1},fun2 <- function(x){x-1})invoke_map(lst,x = 1:5)[[1]][1] 2 3 4 5 6[[2]][1] 0 1 2 3 4
