22

I am trying to use rbind on them. But I need a list of all the dataframes that are already in my global environment. How can I do it?

Code I used to import the 20 csv files in a directory. Basically, have to combine into a single dataframe.

temp = list.files(pattern = "*.csv")
for (i in 1:length(temp)) assign(temp[i], read.csv(temp[i]))
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
maximusyoda
  • 595
  • 3
  • 8
  • 17

6 Answers6

33

This function should return a proper list with all the data.frames as elements

dfs <- Filter(function(x) is(x, "data.frame"), mget(ls()))

then you can rbind them with

do.call(rbind, dfs)

Of course it's awfully silly to have a bunch of data.frames lying around that are so related that you want to rbind them. It sounds like they probably should have been in a list in the first place.

I recommend you say away from assign(), that's always a sign things are probably afoul. Try

temp <- list.files(pattern="*.csv")
dfs <- lapply(temp, read.csv)

that should return a list straight away.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • Yeah, I think I am being silly. But I don't know the proper way to do it. Basically, I have 20 csv files, which I want to combine into one dataframe. Can you help with that from the start? I have attached the code I am using to import them – maximusyoda Aug 26 '14 at 16:01
  • @maximusyoda I've updated with how to read into a list with `lapply` – MrFlick Aug 26 '14 at 16:09
12

From your posted code, I would recommend you start a new R session, and read the files in again with the following code

do.call(rbind, lapply(list.files(pattern = ".csv"), read.csv))
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
  • This looks interesting..I am trying to do exactly this. By doing in one line. But I am getting this error: Error in read.table(file = file, header = header, sep = sep, quote = quote, : more columns than column names – maximusyoda Aug 26 '14 at 16:08
  • 1
    Then you'll have to do some checking. Start with `lapply(list.files(pattern = ".csv"), read.csv)` and go through that list to see what the problem is (look at `dim` of each). It's really hard to diagnose a problem that we can't see. Perhaps provide a small bit of data. – Rich Scriven Aug 26 '14 at 16:11
7

The ls function lists all things in your environment. The get function gets a variable with a given name. You can use the class function to get the class of a variable.

If you put them all together, you can do this:

ls()[sapply(ls(), function(x) class(get(x))) == 'data.frame']

which will return a character vector of the data.frames in the current environment.

MentatOfDune
  • 309
  • 1
  • 9
  • Does this work? I only get a list of filenames in a directory rather than the dataframes in the environment. – maximusyoda Aug 26 '14 at 15:51
  • @maximusyoda No problem. ls lists environment stuff, dir lists the files. Don't forget to accept one of the answers. – MentatOfDune Aug 26 '14 at 16:04
  • No support for elements with multiple classes unfortunately, like tibbles. Great try though! – MS Berends Dec 10 '17 at 15:28
  • 1
    Hello MentatOfDune, thanks to you I discovered the **get()** function in R and solved a very interesting problem! – fran496 Mar 27 '19 at 20:28
7

If you only have data.frames with the same number of columns and column names in you global environment, the following should work (non-data.frame object don't matter):

do.call(rbind, eapply(.GlobalEnv,function(x) if(is.data.frame(x)) x))
James
  • 65,548
  • 14
  • 155
  • 193
6

This is a slight improvement on MentatOfDune's answer, which does not catch data.frames with multiple classes:

ls()[grepl('data.frame', sapply(ls(), function(x) class(get(x))))]
Jonathan Hill
  • 1,745
  • 15
  • 25
5

To improve MentatOfDune's answer (great username by the way):

ls()[sapply(ls(), function(x) any(class(get(x)) == 'data.frame'))]

or even more robust:

ls()[sapply(ls(), function(x) is.data.frame(get(x)))]

This also supports tibbles (created with dplyr for example), because they contain multiple classes, where data.frame is one of them.

A readable version to get TRUEs and FALSEs using R 4 and higher:

ls() |> sapply(get) |> sapply(is.data.frame)

Finally super, super robust, also for package developers:

ls()[sapply(ls(), function(x) is.data.frame(eval(parse(text = x), envir = globalenv())))]
MS Berends
  • 4,489
  • 1
  • 40
  • 53