19

I have a list of lists that have names.

I want to add them all together into a dataframe but keep all the columns

past_earnings_lists[1]

successfully returns one list from the list of lists

names(past_earnings_lists)[1]

successfully returns the name of the list

past_earnings <- melt(past_earnings_lists)

puts all the data in one data frame but doesn't keep structure

past_earnings <- as.data.frame.matrix(past_earnings_lists$ADBE)

Successfully takes one list and keeps the structure but doesn't add the name of the list to the dataframe.

For example, adbe has 7 columns and 30 rows; I want it to add an 8th column with the name, adbe, and append it to a dataframe with all the other lists doing the same.

structure

I want a dataframe with the results being:
  sym  v1 v2 v3 v4 v5 v6 v7
1 adbe  1  2  3  4  5  6  7
2 adbe  1  2  3  4  5  6  7
3 air   1  2  3  4  5  6  7
4 air   1  2  3  4  5  6  7
5 alog  1  2  3  4  5  6  7
and so on
5
  • 7
    this isn't going to fly without a reproducible example Commented Sep 19, 2017 at 21:55
  • 1
    Agreed that its unlikely you will find help without providing data structure to make it a reproducible example, but you may find the bind_rows function from dplyr helpful using the .id parameter to concatenate your lists while generating a new variable identifying the name of the list. dplyr.tidyverse.org/reference/bind.html Commented Sep 19, 2017 at 22:38
  • there, i've added a screenshot Commented Sep 19, 2017 at 22:49
  • It's still not clear. Do you have a list, or a list of lists? Can you include the output of str or dput of past_earnings_list? Commented Sep 20, 2017 at 5:38
  • Also note that doing mylist[1] returns a sublist, whereas mylist[[1]] returns the element itself (see the double brackets). Commented Sep 20, 2017 at 5:40

3 Answers 3

42

This might work

library(purrr)
ans <- map_df(past_earnings_lists, ~as.data.frame(.x), .id="id")

It uses map_df, which will map over lists and convert the result to data frames (if possible). Use the .id argument to add names to each data frame as a column.

Sign up to request clarification or add additional context in comments.

2 Comments

That's great:)! How can I revert this one though?
What do you mean?
6

as @dshkol commented, the easiest is to use dplyr::bind_rows:

d = data.frame(letter = LETTERS, number = 1:26)
d.list = list(d1 = d, d2 = d)
d.all = dplyr::bind_rows(d.list, .id = "variable")

You can also do this in base R with rbind and do.call:

d.all = do.call(rbind, d.list)

However, this will not give you a column containing the list names. You could parse it from the row.names though:

d.all["variable"] = unlist(lapply(
  strsplit(row.names(d.all), ".", fixed = TRUE), function(x) x[[1]])
)

Alternatively, loop through your data frames frames and add the label manually prior to binding:

for (n in names(d.list))
  d.list[[n]]['name'] = n
d.all = do.call(rbind, d.list)

However, it looks like your data frames don't have column names. I think you'll need to fix that for either solution to work.

1 Comment

it doesn't seem to be working, added more information on what output i would like
2

@mikeck was in right track. Splitting string using . is tricky as . regex matches any character. So we need escape character \ before the .. For anyone who wants to accomplish this with base R, you may try this:

df <- do.call(rbind, list)
df$listname <- lapply(strsplit(row.names(df), "\\."), '[[', 1)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.