使用purrr的map函数输入在R中创建一个命名列表作为输出

Mic*_*ael 15 r list named purrr

我在R中使用purrr包的map函数,它给出了一个列表作为输出.现在我希望输出是基于输入的命名列表.下面给出一个例子.

input <- c("a", "b", "c")
output <- purrr::map(input, function(x) {paste0("test-", x)})
Run Code Online (Sandbox Code Playgroud)

从这里我想使用以下方法访问列表的元素:

output$a
Run Code Online (Sandbox Code Playgroud)

要么

output$b
Run Code Online (Sandbox Code Playgroud)

akr*_*run 22

我们只需要命名 list

names(output) <- input
Run Code Online (Sandbox Code Playgroud)

然后根据名称提取元素

output$a
#[1] "test-a"
Run Code Online (Sandbox Code Playgroud)

如果这需要使用 tidyverse

library(tidyverse)
output <- map(input, ~paste0('test-', .)) %>% 
                                setNames(input)
Run Code Online (Sandbox Code Playgroud)

  • 出于这个原因,仅供参考`purrr` 从`rlang` 导入`set_names()`。并不是说`base::setNames()` 之间有什么显着区别... (2认同)
  • @AndersSwanson有很大的不同,特别是您可以执行x%&gt;%set_names()%&gt;%map(fn),这是针对此问题的推荐解决方案。 (2认同)

Mih*_*iha 10

推荐的解决方案:

c("a", "b", "c") %>% 
    purrr::set_names() %>% 
    purrr::map(~paste0('test-', .))
Run Code Online (Sandbox Code Playgroud)

  • 杰出的。我们预先设定了名称。这也适用于 *map_dfc*,并避免在地图后设置名称时收到的“重复名称的重命名警告”。 (3认同)

Hol*_*ndl 5

可接受的解决方案有效,但存在重复的参数(input)的问题,当使用带有的管道时,该参数可能会导致错误并中断流程%>%

一种替代解决方案是使用更多的%>%操作员力量

1:5 %>% { set_names(map(., ~ .x + 3), .) } %>% print # ... or something else
Run Code Online (Sandbox Code Playgroud)

这从管道中引出了争议,但仍然缺乏一些美感。替代方法可以是小助手方法,例如

map_named = function(x, ...) map(x, ...) %>% set_names(x)

1:5 %>% map_named(~ .x + 1)
Run Code Online (Sandbox Code Playgroud)

这看起来已经更加漂亮和优雅了。并且将是我的首选解决方案。

最后,purrr::map在自变量是字符或整数向量的情况下,甚至可以覆盖并在这种情况下生成命名列表。

map = function(x, ...){
    if (is.integer(x) | is.character(x)) {
        purrr::map(x, ...) %>% set_names(x)
    }else {
        purrr::map(x, ...) 
    }
}

1 : 5 %>% map(~ .x + 1)
Run Code Online (Sandbox Code Playgroud)

但是,最佳解决方案是purrr开箱即用地实现这种行为。

  • 我的直觉是,`purrr`维护者不喜欢它,因为它根据输入创建不同的语义。我以为他们喜欢一些更明确的方法,例如带有参数,但这也将支持用例。而且,我猜在很多情况下,它都会破坏向后兼容性。但是可以肯定的是,为什么不问问,请参见https://github.com/tidyverse/purrr/issues/691 (2认同)