0

I would like to transform a list of data frames to one big data frame. The problem is, that I only have the list and not the separate data frames. An additional column with the names of data frames and without the rownames should be included in the new data frame.

Here's what I tried:

d1 <- data.frame(x = c(1.1,2.0,3.5), y = c(4.1,5.1,6.3))
d2 <- data.frame(x = c(3.3,2.7,1.9,2.9,1.9),y = c(6.4,5.2,2.4,3.0,5.1))
d3 <- data.frame(x = c(3.4,2.7,1.8,0.2),y = c(6.2,5.0,4.1,0.5))

my.list <- list(green = d1, blue = d2, yellow = d3)

The target data frame should look like this:

target.df <- data.frame(colour = c(rep("green",nrow(d1)), rep("blue", nrow(d2)), rep("yellow", nrow(d3))), 
                        x = c(1.1,2.0,3.5, 3.3,2.7,1.9,2.9,1.9, 3.4,2.7,1.8,0.2),
                        y = c(4.1,5.1,6.3, 6.4,5.2,2.4,3.0,5.1, 6.2,5.0,4.1,0.5)
                        )

The code

my.df <- do.call(rbind.data.frame, my.list)

produces a dataframe with row names from the names of data frames instead of an extra column.

I tried this:

new.df <- stack(my.list)

But there is Error in stack.default(my.list) : at least one vector element is required

How can I produce the target data frame?

yPennylane
  • 760
  • 1
  • 9
  • 27
  • 2
    @Sotos: This is not a duplicate, because I want to create a data frame out of a LIST. In your related question the starting points are data frames, not a list! – yPennylane Jul 12 '17 at 11:04
  • 1
    Yes it is a duplicated. Try any solution on your list. If you see the question it starts with data frames that are then put in a list! The answer you accepted is the same as one of the answers in the dupe – Sotos Jul 12 '17 at 11:17
  • 2
    Ok. But the solution provided by akrun is very simple and effective... – yPennylane Jul 12 '17 at 11:22
  • 2
    The same one exists in the dupe as well. Give it a read and tou will find a lot of simple answers in there – Sotos Jul 12 '17 at 11:23
  • 2
    `library(tidyr) separate_rows(df, VAR, sep='\\s+')` is not the same as `do.call(rbind, unname(Map(cbind, colour = names(my.list), my.list)))`. The answer to this question here doesn't use the package tidyr. It uses rbind, unname, Map ... The answer `mget(ls(pattern = "df\\d+")) %>% map_df(I, .id = "src")` is much more complicated than the answer provided here. – yPennylane Jul 12 '17 at 11:27
  • 2
    yes it is working. but I still like the FIRST solution from akrun: `do.call(rbind, unname(Map(cbind, colour = names(my.list), my.list)))`. – yPennylane Jul 12 '17 at 11:37
  • And please tell me how that solution is simpler than this: `do.call(rbind, list(df1 = df1, df2 = df2))` – Sotos Jul 12 '17 at 11:40
  • 2
    `do.call(rbind, list(df1 = d1, df2 = d2))` result: `x y df1.1 1.1 4.1 df1.2 2.0 5.1 df1.3 3.5 6.3 df2.1 3.3 6.4 df2.2 2.7 5.2 df2.3 1.9 2.4 df2.4 2.9 3.0 df2.5 1.9 5.1` is not what I wanted.... – yPennylane Jul 12 '17 at 11:43
  • I m done with this. You claimed that your question wasn't a duplicate but It clearly is. It is not a matter of what solution YOU like. That was not your initial comment. You comment was *@Sotos: This is not a duplicate, because I want to create a data frame out of a LIST. In your related question the starting points are data frames, not a list!* Have a nice day! – Sotos Jul 12 '17 at 11:45
  • 2
    Well I didn't find the solution by searching for "Transform list consisting of multiple data frames"... No need to become aggressive, I think. – yPennylane Jul 12 '17 at 11:47
  • 3
    There's a difference between not having found something, and protesting when someone points out the question is a duplicate. The next persons that searches that will find your question and the link to the duplicate, which all the answers there. Everybody wins. – Axeman Jul 12 '17 at 11:52
  • 2
    I think its not usefull to hide the answers of question by masking the questions. If I am looking for transformation of a list to a dataframe then I don't look for how to append data frames... Maybe I'm wrong, but for me the solution and the question were useful. – yPennylane Jul 12 '17 at 11:55
  • 5
    You are combining several data.frames into one, which is exactly what that other question was. There's no problem in that you didn't make that connection, others can help out and point you to the other question (which they did). There's just no need to rehash all the possible answers here, but we rather should just link your question to that one. That means we get to keep all the answer in one place and up to date. Future readers can still find this question with your phrasing, which will point them to the correct duplicate link. No answers are "hidden". – Axeman Jul 12 '17 at 12:00

1 Answers1

4

We can use Map to do this

do.call(rbind, unname(Map(cbind, colour = names(my.list), my.list)))

Result:

do.call(rbind, unname(Map(cbind, colour = names(my.list), my.list)))
   colour   x   y
1   green 1.1 4.1
2   green 2.0 5.1
3   green 3.5 6.3
4    blue 3.3 6.4
5    blue 2.7 5.2
6    blue 1.9 2.4
7    blue 2.9 3.0
8    blue 1.9 5.1
9  yellow 3.4 6.2
10 yellow 2.7 5.0
11 yellow 1.8 4.1
12 yellow 0.2 0.5

Or if we are using dplyr, then bind_rows have the option .id

library(dplyr)
bind_rows(my.list, .id = 'colour')
yPennylane
  • 760
  • 1
  • 9
  • 27
akrun
  • 874,273
  • 37
  • 540
  • 662