Alwin
Alwin

Reputation: 361

R: Reorganise 2D list of dataframes into one dataframe

This is possibly a simple question, but most of my R experience is with dataframes and dplyr. I have list of lists, where the inner list contains one 'information' dataframe and one 'results' dataframe (see example below).

# Sample code for my data structure
data <- list(
  list(data.frame(subject = "A", year = 2016),
       data.frame(results = c(1, 2, 3), time = c(4, 5, 6))
  ),
  list(data.frame(subject = "B", year = 2017),
       data.frame(results = c(7, 8, 9), time = c(10, 11, 12))
  )
)

While this has been great for analysing data in inner lists, I've struggled to do 'cross-list' analysis. What I'm trying to do is reshape my data as shown below.

# Dataframes in lists in lists (current)
    [[1]]
    [[1]][[1]]
      subject year
    1       A 2016
    [[1]][[2]]
      results time
    1       1    4
    2       2    5
    3       3    6
    [[2]]
    [[2]][[1]]
      subject year
    1       B 2017
    [[2]][[2]]

# Single dataframe (goal)
      subject year results time
    1       A 2016       1    4
    2       A 2016       2    5
    3       A 2016       3    6
    4       B 2017       7   10
    5       B 2017       8   11
    6       B 2017       9   12

I've searched online already, but most of the solutions are of a single list of dataframes not lists of lists.

My best effort so far is using for loops (see below), but as my actual data is much larger (both rows and columns) I'm trying to work out a more efficient solution.

df = data.frame()
for (i in (1:length(data))) {
  df = rbind(df,
             cbind(data[[i]][[1]], data[[i]][[2]]))
}

Cheers!

Upvotes: 1

Views: 83

Answers (3)

russellpierce
russellpierce

Reputation: 4711

package:data.table does this well with rbindlist(..., fill = TRUE). Just convert back to data.frame when you're done.

Upvotes: 1

Feng
Feng

Reputation: 613

Since you are familiar with dplyr, try this:

bind_rows(lapply(data,function(i)do.call(cbind,i)))

PS. I found bind_cols does not work well. Maybe it is a little bug?

Upvotes: 2

utubun
utubun

Reputation: 4520

Might be:

do.call(rbind, lapply(1:length(data), 
                      function(i) do.call(cbind, data[[i]])
                      )
        ) 

Upvotes: 1

Related Questions