【问题标题】:Pass multiple functions to purrr:map将多个函数传递给 purrr:map
【发布时间】:2018-05-05 00:47:55
【问题描述】:

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

funs <- c(median, mean)

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

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

我查看了compose,但该函数的作用有所不同。

【问题讨论】:

    标签: r tidyverse purrr


    【解决方案1】:

    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】:

      这是我的小步骤解决方案(取决于您所说的“一次”):

      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))
      

      【讨论】:

      • 这是一种有效的方法,尽管我希望有更直接的方法。谢谢!
      【解决方案3】:

      您想使用 map() 将多个函数应用于数据帧,但是(显然)没有 map() 变体可以完全做到这一点,只有部分功能。对于多函数部分,我们有 invoke_map(),对于数据帧上的多参数部分,我们有 pmap()。

      invoke_map() 允许同时使用多个函数。例如,如果我们要为均匀分布和正态分布生成 5 个随机变量,代码为:

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

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

      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 中的每一列。

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

      更多关于invoke_map()pmap() 工作原理的信息。

      【讨论】:

      • 谢谢,这很有帮助。不过,我希望解决方案更简单。代码不易阅读。
      • 也许这段代码更清楚:mtcars %&gt;% purrr::map_dfr(mosaic::favstats)
      猜你喜欢
      • 2021-12-07
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 1970-01-01
      • 2020-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多