【问题标题】:foreach: Keep namesforeach:保留名称
【发布时间】:2015-02-01 06:49:40
【问题描述】:

有没有办法让 foreach() 返回一个命名的 list/data.frame。例如

foo <- list(a = 1, b = 2)
bar <- foreach (x = foo) %do% { x * 2 }

返回list(2, 4)。我希望它返回list(a = 2, b = 4)

另外,有没有办法从循环体内访问名称?

(我对在 foreach 循环之后分配名称的解决方案不感兴趣。)

问候

【问题讨论】:

  • 不确定foreach 是否具有此功能。但是,您可以将循环更改为foreach(i = seq_along(foo)) {x &lt;- foo[[i]]; ...},这将允许您通过names(foo)[i]访问每个元素的名称
  • 您也可以使用x = Map(structure, .Data=lapply(foo, list), names=names(foo)) 来获取循环内的名称,就像循环使用[ 而不是[[ 来访问foo 的元素一样。

标签: r foreach


【解决方案1】:

我曾经与foreach 合作,但切换到purrr 我不会回头。

purrr 提供了一系列映射函数,使使用命名列表(和列表,以及 data.frames...)变得轻而易举。所有映射操作都保留名称。

library("purrr")

foo <- list(a = 1, b = 2)
bar <- map(foo, ~ .x * 2)

# $a
# [1] 2
# $b
# [1] 4

简洁明了,你真的无法超越。

另外,有没有办法从循环体内访问名称?

肯定有:?imap

bar <- imap(foo, function(elem, name) {
    print(paste("Processing", name))
    elem * 2
})

或匿名风格:

bar <- imap(foo, ~ {print(paste("Processing", .y)) ; .x * 2})

【讨论】:

  • 这很好,但是foreach 可以并行工作,而purrr 不能。此外,虽然furrrpurrr 提供并行操作,但foreach 在使用嵌套循环和%:% 的能力方面仍然是独一无二的。所以你的.final 解决方案赢了!
【解决方案2】:

在需要使用嵌套的 foreach(使用 %:% 运算符)之前,我一直在使用您的解决方案。我想出了这个:

foo <- list(a = 1, b = 2)
bar <- foreach (x = foo, .final = function(x) setNames(x, names(foo))) %do% {
    x * 2
    }

诀窍是使用.final 参数(这是在最终结果中应用一次的函数)来设置名称。这更好,因为它不使用临时变量并且整体更干净。它适用于嵌套列表,因此您可以在结构的多个层中保留名称。

请注意,这只有在 foreach 具有参数 .inorder=T(这是默认值)时才能正常工作。

【讨论】:

  • 这似乎与在foreach 循环之后添加names(bar) &lt;- names(foo) 相同(没有.final)?
【解决方案3】:

感谢您的建议。这是我想出的:

foo <- list(a = 1, b = 2)
bar <- foreach (x = foo, n = names(foo), .combine = c) %do% {
    rv <- list()
    rv[[n]] <- x * 2
    rv
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-16
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-26
    • 2019-10-21
    • 1970-01-01
    相关资源
    最近更新 更多