Rob
Rob

Reputation: 1490

Create list of data.frames with specific rows from list of data.frames

I have a number of data.frames stored in a list (list1) and would like to create a new list (list2) with data.frames where the first contains all the first rows of the data.frames in list1, second contains all the second rows etc. Here is an example:

set.seed(42)
df1 <- data.frame(a=sample.int(100,3),b=sample.int(100,3))
df2 <- data.frame(a=sample.int(100,3),b=sample.int(100,3))

list1 <- list(df1,df2)
list1

[[1]]
  a  b
1 92 84
2 93 64
3 29 51

[[2]]
  a   b
1 74  71
2 14  46
3 65 100

From that I would like to create list 2 that should be as follows:

[[1]]
  a  b
1 92 84
2 74  71

[[2]]
  a   b
1 93 64
2 14  46

[[3]]
  a   b
1 29 51
2 65 100

What would be an efficient way to do this in R?

Upvotes: 2

Views: 69

Answers (3)

Ght ja
Ght ja

Reputation: 21

d = lapply(list1, asplit, 1)
Map(rbind, d[[1]], d[[2]])

Upvotes: 1

M--
M--

Reputation: 28850

Assuming that all the dataframes have the same number of rows and columns, the following works:

split(do.call(rbind, lapply(list1, function(x) x)), 
      rep(1:nrow(list1[[1]]), length(list1)))

# $`1`
# a  b
# 1 92 84
# 2 74  71
# 
# $`2`
# a   b
# 1 93 64
# 2 14  46
# 
# $`3`
# a   b
# 1 29 51
# 2 65 100

Upvotes: 1

akrun
akrun

Reputation: 887118

If all have the same number of rows

nr <- nrow(list1[[1]])
lapply(seq_len(nr), function(i) do.call(rbind, lapply(list1, function(x) x[i,])))

Another option is to bind it to a single data.frame, create a sequence by group and split which would take care of lists with unequal number of rows

library(dplyr)
library(data.table)
bind_rows(list1, .id = 'grp') %>%
    mutate(rn = rowid(grp)) %>%
   {split(.[c('a', 'b')], .$rn)}

Upvotes: 2

Related Questions