将函数应用于参数网格并返回 purrr 中的列表列表 [英] apply a function to a parameter grid and return a list of lists in purrr

查看:39
本文介绍了将函数应用于参数网格并返回 purrr 中的列表列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常使用列表列表将函数(通常是模型调用)应用于参数网格.

I often use lists of lists to apply a function (often a model call) onto a grid of parameters.

这是一个以 paste 作为最终函数的例子:

Here is an example with paste as the ultimate function:

library(tidyverse) #purrr
a=c("A", "B", "C") %>% set_names %>% map(function(x){
  c("m0", "m1") %>% set_names %>% map(function(y){
    c("absolute", "relative") %>% set_names %>% map(function(z){
      paste(x,y,z)
    })
  })
})
a$A$m0$absolute #exact expected output

我正在寻找一种通过更简单的调用获得完全相同结果的方法,可能是使用 crossexpand.gridpmapat_depth.

I am looking for a way to get the exact same result with a simpler call, probably by using cross or expand.grid and pmap or at_depth.

我用 pmap + expand.grid 得到了一些有趣的东西,但它扁平化了结构并去掉了名称:

I got something interesting with pmap + expand.grid but it flattened the structure and droped the names:

b=expand.grid(variable=c("A", "B", "C"), model=c("m0", "m1"), type=c("absolute", "relative")) 
a=b %>% pmap(~{paste(..1,..2,..3)}) #a simple list of length 12

在最好的情况下,函数甚至可以在地图调用中使用名称(variable, model, type)(而不是 ..1,..2,..3 for pmap).

In the best case, the function would even be able to use names (variable, model, type) inside the map call (instead of ..1,..2,..3 for pmap).

有没有办法得到这个?

推荐答案

据我所知,您需要通过参数组合评估一个函数将结果保存在嵌套列表结构中由参数的组合分层定义.使用递归函数,方法是:

As I understand the question, you need to evaluate a function over a combination of parameters and save the result in a nested list structure defined by the combination of parameters hierarchically. Using a function with recursion, an approach is:

ff = function(args, FUN, init = list(), collect = list())
{
    if(!length(args)) return(as.call(c(FUN, collect))) 
    for(i in 1:length(args[[1]])) 
        init[[args[[1]][i]]] = ff(args[-1], FUN = FUN,
                                  collect = c(collect, setNames(list(args[[1]][i]), names(args)[1])))
    return(init)
}

上面的函数返回一个未计算的调用(为了示例;在实际使用中do.call(FUN, collect) 应该替换as.call(c(有趣,收集)))) 用于每个参数组合.例如:

The above function returns an unevaluated call (for the sake of the example; in actual usage do.call(FUN, collect) should replace as.call(c(FUN, collect))) for each combination of parameters. E.g.:

ff(list(param1 = c("a", "b"), param2 = c("A", "B")), c)
#$a
#$a$A
#.Primitive("c")(param1 = "a", param2 = "A")
#
#$a$B
#.Primitive("c")(param1 = "a", param2 = "B")
#
#
#$b
#$b$A
#.Primitive("c")(param1 = "b", param2 = "A")
#
#$b$B
#.Primitive("c")(param1 = "b", param2 = "B")

与示例对比:

b = ff(list(variable = c("A", "B", "C"), 
            model = c("m0", "m1"), 
            type = c("absolute", "relative")),
       paste)

b          #to see the object

identical(a, rapply(b, eval, how = "replace"))
#[1] TRUE

b$A$m0$absolute
#(function (..., sep = " ", collapse = NULL) 
#.Internal(paste(list(...), sep, collapse)))(variable = "A", model = "m0", 
#    type = "absolute")
eval(b$A$m0$absolute)
#[1] "A m0 absolute"

这篇关于将函数应用于参数网格并返回 purrr 中的列表列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆