Search code examples
rpurrr

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


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.


Solution

  • 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)