Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use input of purrr's map function to create a named list as output in R

Tags:

list

r

purrr

named

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 
like image 643
Michael Avatar asked May 12 '17 10:05

Michael


People also ask

What does purrr map do?

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.

What package is map function in R?

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.


2 Answers

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) 
like image 200
akrun Avatar answered Sep 29 '22 18:09

akrun


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.

like image 44
Holger Brandl Avatar answered Sep 29 '22 18:09

Holger Brandl