这是一个我之前在我的代码中编写了故障保护的问题,但我想知道是否有一些更简单的方法被我忽略了。
有时我有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
返回与 第一个 列表相同的名称列表,并按位置进行迭代。因此,odds
中项目 b
和 d
的交换未得到解决,这两个调用的结果不同:
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 对象的属性。 - moodymudskipper