将多个函数传递给purrr:map

时间:2017-11-21 14:07:06

标签: r tidyverse purrr

我想一次将多个函数传递给一个purrr :: map调用,其中函数需要一些参数。作为伪代码:

funs <- c(median, mean)

mtcars %>% 
  purrr::map(funs, na.rm = TRUE) 

此代码运行,但旨在显示我要查找的内容:将多个函数传递给map以及一些参数。

我查看了compose,但该功能有所不同。

3 个答案:

答案 0 :(得分:13)

您希望使用map()将多个函数应用于数据框,但(显然)没有map()变体可以完成此操作,只有部分函数。对于多功能部分,我们有invoke_map(),对于数据帧上的多参数部分,我们有pmap()。

invoke_map()允许一次使用多个功能。例如,如果我们想为均匀和正态分布生成5个随机变量,则代码为:

func <- list(runif, rnorm) 
invoke_map(func, n = 5)

pmap()就像map一样,但它允许将多个参数传递给单个函数。例如,如果我们想要从均值为0且sd = 1的正态分布生成10个随机变量,而且还要从正态分布生成100个随机变量,其中均值= 100且sd = 20,则代码如下所示:

args <- list(mean = c(0, 100), sd = c(1, 20), n = c(10, 100))
pmap(args, rnorm)

要解决您的问题,我们必须按以下方式组合这两个功能:

fun <- function(f) pmap(list(x = mtcars, na.rm = TRUE), f)
param <- list(list(mean), list(median))

invoke_map(.f = fun, .x = param)

这是如何运作的?

  1. 在invoke_map()级别,funparam作为参数,这是我们要应用于mtcars的函数。

  2. 接下来,在fun级别,param中存储的这些函数由pmap()一次一个地应用于mtcars中的每一列。

  3. 注意:要使解决方案真正有意义,请记住invoke_map()和pmap()的参数。

    有关invoke_map()pmap()工作原理的详细信息。

答案 1 :(得分:11)

invoke()及其地图变体已经淘汰,而支持rlang::exec()。从文档中:

这些函数已退出使用exec()。他们不再 正在积极开发中,但我们会将其保留在软件包中 无限期地。

invoke()被淘汰,转而使用更简单的exec()函数 从rlang重新导出。 exec()评估从其构建的函数调用 输入并支持整洁的点

invoke_map()无需替换就可以退出,因为它更多 比使用map(),map2()的相应代码更难理解 和exec()

所以现在等效的方法是:

library(dplyr)
library(purrr)

funs <- c(mean = mean, median = median)
args <- list(na.rm = TRUE, trim = .1) # trim argument non-matching and ignored for median

mtcars %>%
  map_df(~ funs %>%
           map(exec, .x, !!!args), .id = "var")

# A tibble: 11 x 3
   var      mean median
   <chr>   <dbl>  <dbl>
 1 mpg    19.7    19.2 
 2 cyl     6.23    6   
 3 disp  223.    196.  
 4 hp    141.    123   
 5 drat    3.58    3.70
 6 wt      3.15    3.32
 7 qsec   17.8    17.7 
 8 vs      0.423   0   
 9 am      0.385   0   
10 gear    3.62    4   
11 carb    2.65    2  

答案 2 :(得分:2)

这是我的宝贝解决方案(取决于您“一次”的意思):

mtcars %>% 
  map_dbl(~{mean(.x, na.rm = TRUE)}) %>% 
  enframe() %>%
  rename(mean = value) %>%
  as_tibble %>%
  left_join(mtcars %>% 
              map_dbl(~{median(.x, na.rm = TRUE)}) %>% 
              enframe() %>% 
              as_tibble %>%
              rename(median = value))