I'm working on a little problem in R where I'm curious if I can use purrr
to iterate over excel files and sheets.
I've seen a lot of examples where map()
is being given the iterable object directly, i.e. map(1:6, function(x)...
but I'm not sure if/how to do it when I want to generate one of the iterators within the first map
call.
Take this example where we have a folder of excel files, and we want to run the same function on each sheet. So we need two loops, one to loop through the files, and one to iterate through the sheets.
library(tidyverse)
library(readxl)
fileList <- list.files()
customFunction <- function(xlsheet, filePath){
return(1)
}
output <- list()
i <- 1
for (file in fileList){
# get a list of excel sheets in each file
sheet_list <- excel_sheets(file)
for (sheet in sheet_list){
# apply customFunction to each sheet of each file
output[[i]] <- customFunction(sheet, file)
i <- i 1
}
}
I think where I'm getting stuck is that I need arguments from both the first and the second loop in each call of customFunction()
.
Looking at an example from @r2evans in another question, it seems like they're describing something like this:
map(fileList, ~ map(excel_sheets(.x), ~ customFunction(.x, .y)))
But that returns an error in my actual code (and in this example it returns a nested list instead of a single list like the for
loop, noting my example won't fail if the sheet and path aren't correctly passed to customFunction
)
Error in is_string(path) : the ... list contains fewer than 2 elements
And I'm honestly a little lost with the .x
and .y
pronouns
Finally, if this is a silly thing to try to do with purrr
and the for
loop is generally a better solution, that's great feedback too.
CodePudding user response:
Using .x
and .y
can be confusing when you have nested map
s. I usually prefer to use an anonymous function to be clear and yes nested map
's would return nested list. You can use flatten
to get one big list like the for
loop or use unlist
with recursive = FALSE
.
library(purrr)
flatten(map(fileList, function(file)
map(excel_sheets(file), function(sheet)
customFunction(file, sheet))))