Passing multiple dataframes into a function without copying and pasting

Hello,

I come across this problem regularly and I would like to know if there's a more elegant, less redundant way to do this.

For example, say I read x .csv files and I want to remove the first column from each one. I can remove it individually with x[,-1] several times, I can create a function:

rmx <- function(x){
  x[,-1]
}

x <- rmx(x)

But I would still have to type that out x amount of times, or I can store these data frames in a list and pass them through a loop or a function like sapply, but then how do I unlist them so that they return to variables in my global environment so I can continue working with them individually? Or is there another way to do this?

Thanks so much for your help!

Using just functions from base R, you can do something like the following.

Files <- list.files(pattern = "csv$")
ProcessFunc <- function(FileName) {
  tmp <- read.csv(FileName)
  tmp <- tmp[, -1]
  NewName <- sub(".csv", "", FileName)
  assign(NewName, tmp, envir = .GlobalEnv)
  return(FileName)
}
ReturnedNames <- sapply(Files, ProcessFunc)

Just how to construct the NewName variable will depend on where the files are stored and whether you have list.files() return the full path or not. I kept it simple by reading files in my working directory. The ReturnedNames variable serves no purpose other than catching the useless return value of the function. The walk() function from purrr would do this more elegantly.

tidyverse style might be along thse lines.

define a reusable function

rejigthem <- function(list_to_work,
                      action_to_do){
require(tidyverse)
  map(list_to_work,
      ~{
        get(.x) %>%
          action_to_do()
      }) %>% set_names(list_to_work) %>% list2env(
        envir=.GlobalEnv)
}

use it on some example data


(hiris <- head(iris))
(tiris <- tail(iris))


rejigthem(list_to_work =  c("hiris",
                            "tiris"),
          action_to_do = function(x)
                          {select(x,-1)}
          )

# see the change to hiris and tiris
hiris
tiris
1 Like

Amazing! This is exactly what I was looking for. Thank you so much for that function, I'm certain I will be using it regularly. Could you also tell me what the "~" syntax does? I've Googled it before and haven't found an answer.

in this context the tilde is syntax that purrr/tidyverse requires in order to enable us to use shortcut syntax. i.e. within the curly brackets after the tilde, the .x is understood to represent the item from list_to_work that is currently being processed. purrr::map is using ~ (which in R defined a formula) and knows how to interpret it, to turn it into an anonymous function for us, in this case its a function that gets an object from the global environment by its name, and performs action_to_do() on it.

Excellent, really appreciate the help and explanation, thank you so much.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.