Suppose we have a list like this:
l <- list()
l[[1]] <- list()
l[[2]] <- list()
l[[3]] <- list()
names(l) <- c("A", "B", "C")
l[[1]][[1]] <- data.frame(6)
l[[1]][[2]] <- data.frame(3)
l[[1]][[3]] <- data.frame(8)
l[[1]][[4]] <- data.frame(7)
l[[2]][[1]] <- data.frame(5)
l[[2]][[2]] <- data.frame(4)
l[[2]][[3]] <- data.frame(7)
l[[2]][[4]] <- data.frame(9)
l[[3]][[1]] <- data.frame(1)
l[[3]][[2]] <- data.frame(6)
l[[3]][[3]] <- data.frame(2)
l[[3]][[4]] <- data.frame(8)
names(l[[1]]) <- c("aa", "bb", "cc", "dd")
names(l[[2]]) <- c("aa", "bb", "cc", "dd")
names(l[[3]]) <- c("aa", "bb", "cc", "dd")
I want to create a list l2
which contains 4 elements: aa
, bb
, cc
and dd
. Each of these elements would be the dataframe which would contain the values of aa
, bb
, cc
and dd
from list l
and also an ID variable which would indicate if the element came from the A
, B
or C
element of list l
. So if we built the end result from scratch, it would look like this:
l2 <- list()
l2[[1]] <- data.frame(Value = c(6, 5, 1), ID = c("A", "B", "C"))
l2[[2]] <- data.frame(Value = c(3, 4, 6), ID = c("A", "B", "C"))
l2[[3]] <- data.frame(Value = c(8, 7, 2), ID = c("A", "B", "C"))
l2[[4]] <- data.frame(Value = c(7, 9, 8), ID = c("A", "B", "C"))
names(l2) <- c("aa", "bb", "cc", "dd")
However, I cannot build it from scratch, but instead I must "reshape" l
to l2
. What is the best way to do this? Preferred solution is in purrr
.
CodePudding user response:
The key is transpose()
. You could set .id = "ID"
in the inner map_dfr()
to create a new column ID
recording the names of sub-lists where each value comes when row-binding each element together.
library(purrr)
l %>%
transpose() %>%
map(~ map_dfr(.x, set_names, "Value", .id = "ID"))
Output
$aa
ID Value
1 A 6
2 B 5
3 C 1
$bb
ID Value
1 A 3
2 B 4
3 C 6
$cc
ID Value
1 A 8
2 B 7
3 C 2
$dd
ID Value
1 A 7
2 B 9
3 C 8