R:使用嵌套数据结构将不同长度的输入传递给 purrr

R: Passing different-lengthed inputs to purrr with nested data structures

我有两个列表 foobar,其中 length(foo) > length(bar)。我想对 bar 的每个元素应用函数 length(bar) 次,并将每个应用程序的输出存储在自己的列表中,并将函数的所有应用程序存储到 bar 的每个元素在他们自己的列表中。这个嵌套列表输出结构很重要,因为我将它传递给需要嵌套列表的函数。我所拥有和想要的例子在最小的例子中。

虽然这与嵌套 for 循环配合得很好,但我一直在尝试使用 purrrmap 函数来完成此操作。我设法通过创建 (a) length(bar) 的列表来做到这一点,其中每个元素都是 foo,(b) 将这个新列表和 bar 传递给 [=] 中的匿名函数22=],然后 (c) 将其传递给 purrr:map().

中的匿名函数

虽然这行得通,但似乎与 purrr 的目的背道而驰:

purrr 中是否有其他方法可以处理不同长度的列表而不是我的方法?我如何修改我的代码(下面的最小示例)以更好地利用 purrr 的语法?一个想法 () 是使用 cross() 或一些等价物来生成单个对象以传递给 pmap(),但我不知道如何生成嵌套列表结构。

library(purrr)

# Example data: 2 different-length lists
foo <- list(1, 2, 3)
bar <- list("df1", "df2")

# Desired output:
out <- list(list("df1_1", "df1_2", "df1_3"),
            list("df2_1", "df2_2", "df2_3"))

# Distinctive features of output:
#length(out) == length(bar)
#length(out[[1]]) == length(out[[2]])
#length(out[[1]]) == length(foo)

# Can use purrr::pmap but this will concurrently
# iterate through each element of inputs ("in
# parallel") so need to create same-length inputs
foo_list <- rep(list(foo), 2)

# Pass our inputs to pmap then use map to iterate
# over foo contained in each foo_list element.
purrr::pmap(list(foo_list, bar),
            function(foo, bar) {
              map(foo, function(i) {
                paste0(bar, "_", i)
              })
            })

考虑使用嵌套 map。循环 'bar' list,然后循环 'foo' 和 paste。这将 return 嵌套 list 正如 OP 预期的那样

library(purrr)
out2 <- map(bar, ~ map(foo, function(y) paste0(.x, '_', y)))
identical(out, out2)
#[1] TRUE

base R 中的等效选项是

lapply(bar, function(x) lapply(foo, function(y) paste0(x, '_', y)))

或者使用 base R,我们可以使用 outer,创建一个 matrix 的字符串,然后按行拆分(asplitMARGIN 作为1), 变成 vectorlist,遍历 list 并将 vector 的每个元素转换为具有 [=28= 的 list 元素]

out3 <- lapply(asplit(outer(bar, paste0('_', foo), FUN = paste0), 1), as.list)
identical(out, out3)
#[1] TRUE