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 inmap()
: !.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.
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:
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))
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)))
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)))