Search code examples
rlapply

lapply returning "X[[i]]" instead of named output


I want to dynamically run saveRDS across a list of data frames and use each data frame name in the file path.

I've tried this and a single call works:

savedfs <- function(df){
  df2=head(df)
  dir_name = "."
  file_name = deparse1(substitute(df))
  file_path = file.path(dir_name, paste0(file_name,".RDS"))
  saveRDS(df2, file = file_path)
}
    
savedfs(df=cars)
file.exists("./cars.RDS")
[1] TRUE

However, running a named list returns odd output:

dflist <- list(cars, mtcars, iris)
names(dflist) <- c("cars", "mtcars", "iris")

lapply(dflist, savedfs)
$cars
NULL

$mtcars
NULL

$iris
NULL

This last call produces file "./X[[i]].RDS"


Solution

  • Preserving your attempted code as much as possible, you should be able to accomplish this with two minor adjustments. First, add a names argument to your function (here, df_name) to replace deparse(...)and second run lapply on the names, not the list itself:

    savedfs <- function(df, df_name) {
      df2 <- head(df)
      dir_name <- "."
      file_path <- file.path(dir_name, paste0(df_name, ".RDS"))
      saveRDS(df2, file = file_path)
    }
    
    dflist <- list(cars, mtcars, iris)
    names(dflist) <- c("cars", "mtcars", "iris")
    
    lapply(names(dflist), \(x) {
      savedfs(dflist[[x]], x)
    })
    

    As @Friede mentions in the comments, you could also use a for loop and avoid lapply altogether (and the associated extraneous printing that comes with it):

    for(x in names(dflist)) savedfs(dflist[[x]], x)