J'utilise la fonction map du paquet purrr dans R qui donne en sortie une liste. Maintenant, je voudrais que la sortie soit une liste nommée basée sur l'entrée. Un exemple est donné ci-dessous.
input <- c("a", "b", "c")
output <- purrr::map(input, function(x) {paste0("test-", x)})
À partir de cela, je voudrais accéder aux éléments de la liste en utilisant:
output$a
Ou
output$b
Nous avons juste besoin de nommer le list
names(output) <- input
puis extraire les éléments en fonction du nom
output$a
#[1] "test-a"
Si cela doit être fait en utilisant tidyverse
library(tidyverse)
output <- map(input, ~paste0('test-', .)) %>%
setNames(input)
La solution acceptée fonctionne, mais souffre d'un argument répété (input
) qui peut provoquer des erreurs et interrompre le flux lors de l'utilisation de la tuyauterie avec %>%
.
Une solution alternative consisterait à utiliser un peu plus de puissance du %>%
opérateur
1:5 %>% { set_names(map(., ~ .x + 3), .) } %>% print # ... or something else
Cela prend l'argument de la pipe mais manque encore de beauté. Une alternative pourrait être une petite méthode d'aide telle que
map_named = function(x, ...) map(x, ...) %>% set_names(x)
1:5 %>% map_named(~ .x + 1)
Cela semble déjà plus joli et élégant. Et ce serait ma solution préférée.
Enfin, nous pourrions même écraser purrr::map
dans le cas où l'argument est un vecteur caractère ou entier et produit une liste nommée dans un tel cas.
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)
Cependant, la solution optimale serait que purrr
implémente un tel comportement hors de la boîte.