A {s,v}apply `USE.NAMES`-like option for `purrr` map family?

IMHO, the USE.NAMES option in {s,v}apply is quite handy. For example, if I supply a char vector as input to e.g. sapply, and use USE.NAMES=T (and simplify=F), I get back a list with element names corresponding to the elements of the input vector.

To use a trivial example,

> sapply(letters[1:5], identity, simplify = F, USE.NAMES = T)
$a
[1] "a"

$b
[1] "b"

$c
[1] "c"

$d
[1] "d"

$e
[1] "e"

The named list is very handy I think. Consider, example, if the input vector was a list of file names and the function being applied was readr::read_csv. We would then get back a list of data frames indexed by their file names.

If I were to use purrr::map, I'd get back a list with no names.

> purrr::map(letters[1:5], identity)
[[1]]
[1] "a"

[[2]]
[1] "b"

[[3]]
[1] "c"

[[4]]
[1] "d"

[[5]]
[1] "e"

I could do the following.

> purrr::map(letters[1:5], identity) %>% 
      magrittr::set_names(letters[1:5])
$a
[1] "a"

$b
[1] "b"

$c
[1] "c"

$d
[1] "d"

$e
[1] "e"

That does the job. But am I missing a trick? Is the better, easier, more recommended way of accomplishing this?

1 Like

I too have asked myself the same question and my understanding is that adding such an option is unlikely to happen, but I might be wrong.

The only thing I would change in your purrr example is where you name the list, so something like this:

library(magrittr)

magrittr::set_names(letters[1:5], letters[1:5]) %>% 
  purrr::map(identity)
#> $a
#> [1] "a"
#> 
#> $b
#> [1] "b"
#> 
#> $c
#> [1] "c"
#> 
#> $d
#> [1] "d"
#> 
#> $e
#> [1] "e"

Created on 2019-08-11 by the reprex package (v0.3.0)

I would say that this makes both parts clearer about what you are doing.

1 Like

You can even do it a little bit shorter. The set_names function takes automatically the vector values and sets them as names.

purrr::map(purrr::set_names(letters[1:5]), identity)
2 Likes