Search code examples
rdataframepurrr

How do I use functions inside map() in R, using the recommended way of passing arguments?


I thought I understood how map() works but apparently I don't. I have a vector of filenames that correspond to real files in the working directory:

file_names <- c("filename1", "filename2", "filename3")

This works:

library(tidyverse)

data <- data_frame(filename = file_names) %>%
  mutate(content = map(file_names, read_tsv))

But when I want to add arguments to read_tsv by using the recommended format map(\\(x) f(x, arg1, arg2))

data <- data_frame(filename = file_names) %>%
 mutate(content = map(\(file_names) read_tsv(file_names, skip = 1, col_names = FALSE)))

I get an error:

Error in mutate(): ℹ In argument: content = map(function(file_names) read_tsv(file_names, skip = 1, col_names = FALSE)). Caused by error in map(): ! .x must be a vector, not a function.

I tried changing the file_names to .x and similar but I don't know how it's suppose to work. Any help appreciated.


Solution

  • From ?map you can see that:

    map(.x, .f, ..., .progress = FALSE)

    Therefore you will still need .x (A list or atomic vector) in your map function, which would be your file_names vector. You should supply the function in the second argument (.f), which allows several formats for specifying it:


    1. A named function

    This is not the recommended way.

    We now generally recommend against using ... to pass additional (constant) arguments to .f

    data_frame(filename = file_names) %>%
      mutate(content = map(file_names, read_tsv, skip = 1, col_names = FALSE))
    

    2. An anonymous function

    You can define an anonymous function within map, with the format function(argument) foo(argument) or shorthand \(argument) foo(argument), where foo is the actual function you are applying in map.

    data_frame(filename = file_names) %>%
      mutate(content = map(file_names, \(file_names) read_tsv(file_names, skip = 1, col_names = FALSE)))
    

    3. A formula

    This is more of a "tidyverse" way of specifying functions, where you must combine ~ and .x to represent the first argument of the function.

    data_frame(filename = file_names) %>%
      mutate(content = map(file_names, ~read_tsv(.x, skip = 1, col_names = FALSE)))