Search code examples
rpurrr

How to use nested anonymous functions in purrr map2?


I'm looking to iterate over a list of dataframes and add a suffix to all of the column names. I want the suffix to be the name of the dataframe.

The result I want essentially looks like this:

library(tidyverse)
list(
  mtcars %>% rename_with(~str_c(., "_", deparse(substitute(mtcars)))) %>% names(),
  iris %>% rename_with(~str_c(., "_", deparse(substitute(iris)))) %>% names()
)
#> [[1]]
#>  [1] "mpg_mtcars"  "cyl_mtcars"  "disp_mtcars" "hp_mtcars"   "drat_mtcars"
#>  [6] "wt_mtcars"   "qsec_mtcars" "vs_mtcars"   "am_mtcars"   "gear_mtcars"
#> [11] "carb_mtcars"
#> 
#> [[2]]
#> [1] "Sepal.Length_iris" "Sepal.Width_iris"  "Petal.Length_iris"
#> [4] "Petal.Width_iris"  "Species_iris"

Created on 2023-06-28 with reprex v2.0.2

I tried doing this but it didn't work. I think the nested anonymous functions are making me confused. I'm not sure how to reference .x (the dataframe), .y (the dataframe name), and the column name. Please help!

imap(list(mtcars, iris), ~rename_with(.x, ~ str_c(., "_", .y)))

Solution

  • imap() requires the elements to have names else it uses their index. You can use lst() which automatically names its elements (or manually name things, e.g. list(mtcars = mtcars, ...). You can also use a base lambda function in the rename_with() call:

    library(purrr)
    library(stringr)
    library(dplyr)
    
    imap(lst(mtcars, iris), ~ rename_with(.x, \(var) str_c(var, "_", .y)))
    

    Alternatively, avoiding anonymous functions and relying on argument forwarding:

    imap(lst(mtcars, iris), rename_with, .cols = everything(), .fn = str_c, sep = "_")