【问题标题】:R: Passing different-lengthed inputs to purrr with nested data structuresR:使用嵌套数据结构将不同长度的输入传递给 purrr
【发布时间】:2021-08-05 02:12:01
【问题描述】:

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

虽然这适用于嵌套的 for 循环,但我一直在尝试使用 purrrmap 函数来实现这一点。我设法通过创建 (a) length(bar) 列表,其中每个元素是 foo,(b) 将这个新列表和 bar 传递给 purrr::pmap() 中的匿名函数,然后 (c ) 将其传递给 purrr:map() 中的匿名函数。

虽然这行得通,但它似乎与purrr 的目的大相径庭:

  • 我定义的是匿名函数,而不是 .x.y~ 语法。
  • 我没有传递我的原始列表(长度不同),而是将一个列表转换为嵌套列表以匹配另一个列表的长度。这可能会占用大量内存、速度慢等。
  • 我正在使用嵌套列表而不是更扁平的列表/数据框,然后我将其划分为我想要的数据结构。

purrr 中是否有另一种处理不同长度列表的方法而不是我的方法?我如何修改我的代码(下面的最小示例)以更好地利用purrr 的语法?一个想法(Handling vectors of different lengths in 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)
              })
            })

【问题讨论】:

  • 你不能更轻松地取消列出并做到这一点

标签: r list mapping purrr data-wrangling


【解决方案1】:

考虑使用嵌套的map。循环遍历“bar”list,然后遍历“foo”和paste。这将返回一个嵌套的 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),变成listvector s,循环list并将vector的每个元素转换为list元素与as.list

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

【讨论】:

  • 优秀。令我困惑的是 .x 是指foo 的元素还是bar 的元素。似乎有些模棱两可。
  • @user3614648 .x 总是返回当前调用的元素。当我们有多个嵌套调用时,最好使用传统的匿名函数,我们可以灵活地将其命名为xy或任何其他名称来区分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 2017-11-10
  • 1970-01-01
相关资源
最近更新 更多