R:使用嵌套数据结构将不同长度的输入传递给 purrr
R: Passing different-lengthed inputs to purrr with nested data structures
我有两个列表 foo
和 bar
,其中 length(foo) > length(bar)
。我想对 bar
的每个元素应用函数 length(bar)
次,并将每个应用程序的输出存储在自己的列表中,并将函数的所有应用程序存储到 bar
的每个元素在他们自己的列表中。这个嵌套列表输出结构很重要,因为我将它传递给需要嵌套列表的函数。我所拥有和想要的例子在最小的例子中。
虽然这与嵌套 for 循环配合得很好,但我一直在尝试使用 purrr
的 map
函数来完成此操作。我设法通过创建 (a) length(bar)
的列表来做到这一点,其中每个元素都是 foo
,(b) 将这个新列表和 bar
传递给 [=] 中的匿名函数22=],然后 (c) 将其传递给 purrr:map()
.
中的匿名函数
虽然这行得通,但似乎与 purrr
的目的背道而驰:
- 我定义的是匿名函数,而不是
.x
、.y
和 ~
语法。
- 我没有传递我的原始列表(长度不同),而是将一个列表转换为嵌套列表以匹配另一个的长度。这可能会占用大量内存、速度慢等。
- 我正在使用嵌套列表而不是扁平化 lists/dataframes 然后我划分到我想要的数据结构中。
在 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
的字符串,然后按行拆分(asplit
和 MARGIN
作为1), 变成 vector
的 list
,遍历 list
并将 vector
的每个元素转换为具有 [=28= 的 list
元素]
out3 <- lapply(asplit(outer(bar, paste0('_', foo), FUN = paste0), 1), as.list)
identical(out, out3)
#[1] TRUE
我有两个列表 foo
和 bar
,其中 length(foo) > length(bar)
。我想对 bar
的每个元素应用函数 length(bar)
次,并将每个应用程序的输出存储在自己的列表中,并将函数的所有应用程序存储到 bar
的每个元素在他们自己的列表中。这个嵌套列表输出结构很重要,因为我将它传递给需要嵌套列表的函数。我所拥有和想要的例子在最小的例子中。
虽然这与嵌套 for 循环配合得很好,但我一直在尝试使用 purrr
的 map
函数来完成此操作。我设法通过创建 (a) length(bar)
的列表来做到这一点,其中每个元素都是 foo
,(b) 将这个新列表和 bar
传递给 [=] 中的匿名函数22=],然后 (c) 将其传递给 purrr:map()
.
虽然这行得通,但似乎与 purrr
的目的背道而驰:
- 我定义的是匿名函数,而不是
.x
、.y
和~
语法。 - 我没有传递我的原始列表(长度不同),而是将一个列表转换为嵌套列表以匹配另一个的长度。这可能会占用大量内存、速度慢等。
- 我正在使用嵌套列表而不是扁平化 lists/dataframes 然后我划分到我想要的数据结构中。
在 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
的字符串,然后按行拆分(asplit
和 MARGIN
作为1), 变成 vector
的 list
,遍历 list
并将 vector
的每个元素转换为具有 [=28= 的 list
元素]
out3 <- lapply(asplit(outer(bar, paste0('_', foo), FUN = paste0), 1), as.list)
identical(out, out3)
#[1] TRUE