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

R:使用嵌套数据结构将不同长度的输入传递给purrr,r,list,mapping,purrr,data-wrangling,R,List,Mapping,Purrr,Data Wrangling,我有两个列表foo和bar,其中length(foo)>length(bar)。我想对bar的每个元素应用函数length(bar)次,并将每个应用程序的输出存储在自己的列表中,将函数的所有应用程序存储在自己的列表中bar的每个元素中。这个嵌套列表输出结构很重要,因为我将它传递给需要嵌套列表的函数。我所拥有和想要的例子在最小的例子中 虽然嵌套for循环可以很好地实现这一点,但我一直在尝试使用purr的map函数来实现这一点。我通过创建一个length(bar)列表,其中每个元素都是foo,(b)

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

虽然嵌套for循环可以很好地实现这一点,但我一直在尝试使用
purr
map
函数来实现这一点。我通过创建一个
length(bar)
列表,其中每个元素都是
foo
,(b)将这个新列表和
bar
传递给
purr::pmap()
中的匿名函数,然后(c)将它传递给
purr:map()中的匿名函数

虽然这是可行的,但它似乎与
purrr
的目的背道而驰:

  • 我定义的是匿名函数,而不是
    .x
    .y
    ~
    语法
  • 我不是传递原始列表(长度不同),而是将一个列表转换为嵌套列表,以匹配另一个的长度。这可能是内存密集型、速度慢等
  • 我使用的是嵌套列表,而不是更扁平的列表/数据帧,然后将它们划分到所需的数据结构中
purrr
中是否有比我的aproach更适合处理不同长度列表的替代方法?如何修改我的代码(下面的最小示例)以更好地利用
purr
的语法?一个想法()是使用
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)
              })
            })
库(purrr)
#示例数据:2个不同长度的列表

foo考虑使用嵌套的
映射。在“条形图”
列表上循环,然后在“foo”和
粘贴上循环。这将返回一个嵌套的
列表
,与OP的预期值相同

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

或者使用
base R
,我们可以使用
outer
,创建字符串的
矩阵
,然后按行(
asplit
,其中
边距
为1)拆分为
向量
列表,在
列表
上循环,并将
向量
的每个元素转换为具有
as.list的
列表
元素

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

out3您不能取消列表并更轻松地执行此操作。让我困惑的是.x是指
foo
的元素还是
bar
的元素。似乎有点含糊不清。@user3614648
.x
总是返回当前调用的元素。当我们嵌套了多个调用时,最好使用传统的匿名函数,我们可以灵活地将其命名为
x
y
或任何其他名称来区分
out3 <- lapply(asplit(outer(bar, paste0('_', foo), FUN = paste0), 1), as.list)
identical(out, out3)
#[1] TRUE