R: Combining nested list items by name

Let's say I have a list structure where it is data.framesnested in each element.

l <- list(A = list(D = data.frame(V1 = seq(3), V2 = LETTERS[1:3]),
                   E = data.frame(V1 = seq(3), V2 = LETTERS[4:6])),
          B = list(D = data.frame(V1 = seq(3), V2 = LETTERS[7:9]),
                   E = data.frame(V1 = seq(3), V2 = LETTERS[10:12])))

$A
$A$D
  V1 V2
1  1  A
2  2  B
3  3  C

$A$E
  V1 V2
1  1  D
2  2  E
3  3  F


$B
$B$D
  V1 V2
1  1  G
2  2  H
3  3  I

$B$E
  V1 V2
1  1  J
2  2  K
3  3  L

I would like to find a way to combine tags Dand E data.framesaccordingly from the parent elements of the list ( A, B), so the result will be like this:

$D
  V1 V2
1  1  A
2  2  B
3  3  C
4  1  G
5  2  H
6  3  I

$E
  V1 V2
1  1  D
2  2  E
3  3  F
4  1  J
5  2  K
6  3  L

I can accomplish this with a loop, but I'm trying to find something more efficient / elegant.

out <- vector("list", length(list))
for(i in c("D","E")){
  out[[i]] <- do.call("rbind", lapply(l, function(x) x[[i]]))
}
+4
source share
3 answers

We smooth out the nested listone listwith 4 elements ( l1), then split'l1' by the names 'l1' after replacing part of the prefix with .using sub. Then we are rbindnested listusing do.call.

l1 <- do.call('c', l)
lapply(split(l1,sub('.*\\.', '', names(l1))),
                      function(x) do.call(rbind, x))

purrr dplyr

library(purrr)
library(dplyr)
transpose(l) %>%
          map(bind_rows)
#$D
#Source: local data frame [6 x 2]

#     V1    V2
#  (int) (chr)
#1     1     A
#2     2     B
#3     3     C
#4     1     G
#5     2     H
#6     3     I

#$E
#Source: local data frame [6 x 2]

#     V1    V2
#  (int) (chr)
#1     1     D
#2     2     E
#3     3     F
#4     1     J
#5     2     K
#6     3     L
+4

, :

l1 <- unlist(l, recursive = FALSE)
D <- do.call(rbind, l1[grepl("\\.D", names(l1))])
E <- do.call(rbind, l1[grepl("\\.E", names(l1))])

, .

+3

I would use a more elegant approach with data.table (not necessarily more efficient):

library(data.table)

lapply(c('E','D'), function(u) rbindlist(lapply(l, `[[`, u)))
#$A
#   V1 V2
#1:  1  D
#2:  2  E
#3:  3  F
#4:  1  J
#5:  2  K
#6:  3  L

#$B
#   V1 V2
#1:  1  A
#2:  2  B
#3:  3  C
#4:  1  G
#5:  2  H
#6:  3  I

In the R database, this can be done using

lapply(c('E','D'), function(u) do.call(rbind, lapply(l, `[[`, u)))
+3
source

Source: https://habr.com/ru/post/1613512/


All Articles