R extract name of object within purrr::map()

Viewed 641

I'm trying to extract the names of objects that are being mapped over within purrr::map(). Here's a simplified example of the problem.

library(tidyverse)

input <- list(df1 = mtcars, df2 = iris)

map(input, ~ deparse(substitute(.x)))

My SO searches led me to the "deparse(subsitute()" trick. But in this example, it returns

$df1
[1] "..1"

$df2
[1] "..1"

instead of what I want, which is

df1
[1] "df1"

$df2
[1] "df2"

In other words, I need to be able to process the names of the objects in the list within a more elaborate lambda function.

Thanks in advance for any help.

2 Answers

We can use imap (which calls map2 to pass the names index) instead of map and extract the list names with .y and the values with .x. Here imap is calling map2

library(purrr)
imap(input, ~ .y)
#$df1
#[1] "df1"

#$df2
#[1] "df2"

Or instead of .x, .y, can also use ..1 and ..2

imap(input, ~ ..2)

Basically imap is calling map2

 imap
  function (.x, .f, ...) 
 {
.f <- as_mapper(.f, ...)
map2(.x, vec_index(.x), .f, ...)
  }

If we want to use map, option is to loop over the names or the sequence of list

map(names(input), ~ .x)

and for subsetting the values, use the [[

map(names(input), ~ input[[.x]])

With map, the .x is only the values of the data and the names of the list are not passed into it


If we want to use base R, then an option is Map

Map(function(u, v) v, input, names(input))

or using lapply

lapply(names(input), function(nm) nm)

You can use map2 and pass data as well as names.

purrr::map2(input, names(input), ~.y)

#$df1
#[1] "df1"

#$df2
#[1] "df2"

Here .x has the data whereas .y has the names of input.

The same can be achieved using Map in base R :

Map(function(x, y) y, input, names(input))

where x is the data and y the names.

Related