【发布时间】:2019-09-11 21:25:30
【问题描述】:
这是一个我之前在代码中编写过故障保护的问题,但我想知道是否有更直接的问题我错过了。
有时我有 2 个(或更多)列表,其中包含需要与 map2 之类的函数一起使用的不同类型的信息——想想 ggplot 对象的命名列表和用于保存的文件路径的命名列表每个的输出。是否有一种内置或轻松添加到管道工作流的方法来确保列表项按名称而不是位置匹配?
考虑一个简单的例子:
library(purrr)
evens <- list(a = 2, b = 4, c = 6, d = 8)
odds <- list(a = 11, d = 9, c = 7, b = 5)
map2 返回一个与 first 列表同名的列表,并按位置进行迭代。因此,b 和 d 项目在 odds 中切换的事实没有得到解决,这两个调用产生了不同的结果:
map2(evens, odds, function(l1, l2) {
paste(l1, l2)
})
#> $a
#> [1] "2 11"
#>
#> $b
#> [1] "4 9"
#>
#> $c
#> [1] "6 7"
#>
#> $d
#> [1] "8 5"
map2(odds, evens, function(l1, l2) {
paste(l1, l2)
})
#> $a
#> [1] "11 2"
#>
#> $d
#> [1] "9 4"
#>
#> $c
#> [1] "7 6"
#>
#> $b
#> [1] "5 8"
我过去所做的是改用 imap 并使用第一个列表的名称来提取另一个列表中的适当项目,但这意味着我的函数参数中不再有第二个列表:
imap(evens, function(l1, name) {
paste(l1, odds[[name]])
})
#> $a
#> [1] "2 11"
#>
#> $b
#> [1] "4 5"
#>
#> $c
#> [1] "6 7"
#>
#> $d
#> [1] "8 9"
如果我想让两个列表的操作更均匀,我可以按名称对它们进行排序,但这感觉很笨拙:
map2(
evens[order(names(evens))],
odds[order(names(odds))],
function(l1, l2) paste(l1, l2)
)
# same output as previous
或者更笨重,制作两个列表的列表,将它们分别排列在另一个 map 中,然后将其通过管道传递到 pmap,因为它需要一个列表列表:
list(evens, odds) %>%
map(~.[order(names(.))]) %>%
pmap(function(l1, l2) paste(l1, l2))
# same output as previous
理想情况下,我想将imap 选项的安全性与map2 的清洁度结合起来。
【问题讨论】:
-
也许使用
transpose(lst(odds, evens))之类的东西并在顶部使用标准map?如果这是您的用例,或者将您的路径设置为 ggplot 对象的属性。