将函数应用于参数网格并返回 purrr 中的列表列表 [英] apply a function to a parameter grid and return a list of lists in 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
我正在寻找一种通过更简单的调用获得完全相同结果的方法,可能是使用 cross
或 expand.grid
和 pmap
或 at_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屋!