r - 对于名称乱序的列表更安全的 purrr::map2
问题描述
这是我之前在我的代码中编写过故障保护的问题,但我想知道是否有一些更简单的东西我错过了。
有时我有 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
返回一个与第一个列表同名的列表,并按位置迭代。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
或者更笨重,制作两个列表的列表,将它们分别排列在 another 中map
,然后通过管道将其输入,pmap
因为它需要一个列表列表:
list(evens, odds) %>%
map(~.[order(names(.))]) %>%
pmap(function(l1, l2) paste(l1, l2))
# same output as previous
理想情况下,我想将imap
选项的安全性与map2
.
解决方案
我们能做的
library(tidyverse)
map2(evens, odds[names(evens)], str_c, sep=' ')
#$a
#[1] "2 11"
#$b
#[1] "4 5"
#$c
#[1] "6 7"
#$d
#[1] "8 9"
如果两个list
名称都是无序的,则遍历其中之一的sort
ed ,提取两个元素并连接names
list
map(sort(names(evens)), ~ str_c(evens[[.x]], odds[[.x]], sep= ' '))
或者为 , 然后创建一个标识符order
,然后将 和 中order
的list
元素list
与map2
i1 <- order(names(evens)) # not sure if this should be avoided
map2(evens[i1], odds[i1], str_c, sep=" ")
推荐阅读
- fortran - 使用变量子字符串时,INDEX 不返回匹配项
- json - 将必填字段应用于引用的 JSON 数据架构
- python - tkinter按钮颜色无故闪烁
- .net - 生成API客户端接口并在前端项目中使用
- mysql - 如何在具有数组条件的mysql中加入两个表
- react-native - react-native 生产 undefined 不是函数错误
- r - 合并两个表并在 R 中保持较小的值
- amazon-redshift - 每当我将其连接到 Redshift 时,如何在每个会话中将我的 SQL 代码保存在 SQL 工作台/J 中?
- python - 查找python文本中是否存在单词的逻辑
- c# - 正则表达式总限制总字符数