Home > database >  Nested list to grouped rows in R
Nested list to grouped rows in R

Time:01-13

I have the following nested list called l (dput below):

> l
$A
$A$`1`
[1] 1 2 3

$A$`2`
[1] 3 2 1


$B
$B$`1`
[1] 2 2 2

$B$`2`
[1] 3 4 3

I would like to convert this to a grouped dataframe where A and B are the first group column and 1 and 2 are the subgroups with respective values. The desired output should look like this:

   group subgroup values
1      A        1      1
2      A        1      2
3      A        1      3
4      A        2      3
5      A        2      2
6      A        2      1
7      B        1      2
8      B        1      2
9      B        1      2
10     B        2      3
11     B        2      4
12     B        2      3

As you can see A and B are the main group and 1 and 2 are the subgroups. Using purrr::flatten(l) or unnest doesn't work. So I was wondering if anyone knows how to convert a nested list to a grouped row dataframe?


dput of l:

l <- list(A = list(`1` = c(1, 2, 3), `2` = c(3, 2, 1)), B = list(`1` = c(2, 
2, 2), `2` = c(3, 4, 3)))

CodePudding user response:

Using stack and rowbind with id:

data.table::rbindlist(lapply(l, stack), idcol = "id")
#     id values ind
#  1:  A      1   1
#  2:  A      2   1
#  3:  A      3   1
#  4:  A      3   2
#  5:  A      2   2
#  6:  A      1   2
#  7:  B      2   1
#  8:  B      2   1
#  9:  B      2   1
# 10:  B      3   2
# 11:  B      4   2
# 12:  B      3   2

CodePudding user response:

You can use enframe() to convert the list into a data.frame, and unnest the value column twice.

library(tidyr)

tibble::enframe(l, name = "group") %>%
  unnest_longer(value, indices_to = "subgroup") %>%
  unnest(value)

# A tibble: 12 × 3
   group value subgroup
   <chr> <dbl> <chr>   
 1 A         1 1       
 2 A         2 1       
 3 A         3 1       
 4 A         3 2       
 5 A         2 2       
 6 A         1 2       
 7 B         2 1       
 8 B         2 1       
 9 B         2 1       
10 B         3 2       
11 B         4 2       
12 B         3 2

CodePudding user response:

Turn the list directly into a data frame, then pivot it into a long format and arrange to your desired order.

library(tidyverse)

lst %>% 
  as.data.frame() %>% 
  pivot_longer(everything(), names_to = c("group", "subgroup"), 
               values_to = "values", 
               names_pattern = "(. ?)\\.(. ?)") %>% 
  arrange(group, subgroup)

# A tibble: 12 × 3
   group subgroup values
   <chr> <chr>     <dbl>
 1 A     1             1
 2 A     1             2
 3 A     1             3
 4 A     2             3
 5 A     2             2
 6 A     2             1
 7 B     1             2
 8 B     1             2
 9 B     1             2
10 B     2             3
11 B     2             4
12 B     2             3

CodePudding user response:

You can combine rrapply with unnest:

library(rrapply)
library(tidyr)
rrapply(l, how = "melt") |>
  unnest(value)

# A tibble: 12 × 3
   L1    L2    value
   <chr> <chr> <dbl>
 1 A     1         1
 2 A     1         2
 3 A     1         3
 4 A     2         3
 5 A     2         2
 6 A     2         1
 7 B     1         2
 8 B     1         2
 9 B     1         2
10 B     2         3
11 B     2         4
12 B     2         3
  • Related