I am using the map function of the purrr package in R which gives as output a list. Now I would like the output to be a named list based on the input. An example is given below.
input <- c("a", "b", "c") output <- purrr::map(input, function(x) {paste0("test-", x)})
From this I would like to access elements of the list using:
output$a
Or
output$b
purrr::map() is a function for applying a function to each element of a list. The closest base R function is lapply() . Here's how the square root example of the above would look if the input was in a list.
The purrr package improves the R's functional programming (FP) toolkit. The map() function in R is categorized under functional programming that allows you to replace many for loops with code that is more concise and clearer to read.
We just need to name the list
names(output) <- input
and then extract the elements based on the name
output$a #[1] "test-a"
If this needs to be done using tidyverse
library(tidyverse) output <- map(input, ~paste0('test-', .)) %>% setNames(input)
Update
Now in 2020 the answer form @mihagazvoda describes the correct approach: simply set_names
before applying map
c("a", "b", "c") %>% purrr::set_names() %>% purrr::map(~paste0('test-', .))
Outdated answer
The accepted solution works, but suffers from a repeated argument (input
) which may cause errors and interrupts the flow when using piping with %>%
.
An alternative solution would be to use a bit more power of the %>%
operator
1:5 %>% { set_names(map(., ~ .x + 3), .) } %>% print # ... or something else
This takes the argument from the pipe but still lacks some beauty. An alternative could be a small helper method such as
map_named = function(x, ...) map(x, ...) %>% set_names(x) 1:5 %>% map_named(~ .x + 1)
This already looks more pretty and elegant. And would be my preferred solution.
Finally, we could even overwrite purrr::map
in case the argument is a character or integer vector and produce a named list in such a case.
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)
However, the optimal solution would be if purrr
would implement such behaviour out of the box.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With