Put all dataframes with names containing a particular string into a single list

Viewed 84

I am trying to write a function that makes a list of dataframes that contain a certain string.

If I write:

objlist <- ls(pattern = "*_results*")
all_dfs <- ls()[sapply(ls(), function(x) any(class(get(x)) == 'data.frame'))]
dfs_list <-  mget(Reduce(intersect, list(objlist, all_dfs)))  

"dfs_list" contains all the dataframes in the environment that contain "_results" (in my particular case it creates a list of 20 dataframes).

However if I try to convert it to a function:

list_dataframes <- function(pattern) {
  objlist <- ls(pattern = pattern)
  all_dfs <- ls()[sapply(ls(), function(x) any(class(get(x)) == 'data.frame'))]
  dfs_list <-  mget(Reduce(intersect, list(objlist, all_dfs)))  
  return(dfs_list)
}

flarp <- list_dataframes("*_results*")

The object "flarp" is a list of 0 elements.

What am I doing wrong here?

2 Answers

That's because of ls(). When you put it in a function you need to specify the environment explicitly, either by name, pos or env arguments, i.e.

f1 <- function() ls()
f1()
#character(0)

f1 <- function() ls(pos = 1)
f1()
#[1] "df" "f1" "rb"

That is because the function creates another "function environment", and since you call ls() from within this function, you will have the list of objects existing within this function. Please consider the following code which sould be clear.

print(ls()) # Globalenv objects
test <- function() { #different envir inside a function
  a <- "test"
  print(ls())
} 
test() # only prints "a" 
test <- function() {
  print(ls(.GlobalEnv))
}
test() # prints all the globalenv objects

Actually, functions use up to as many as four types of environments: enclosing, binding, execution and calling. You can learn more in this in-depth Chapter of Avanced R by Hadley.

Related