将列表列表转换为列表形式重塑为数据框 - R

问题描述

我有下面的列表(list2),其中列表的元素也是一个列表:

> dput(list2)
list(x = list(a = c(0.18,0.7,0.57,0.17,0.94),b = c(0.18,0.94)),y = list(a = c(0.18,z = list(a = c(0.18,0.94)))

生成的列表如下:

names1<-c("a","b")
names2<-c("x","y","z")
list1<-list()
list2<-list()
for(i in names1)
  for(j in names2){{
    set.seed(2)
  list1[[i]]<-round(runif(5),2)
  list2[[j]]<-list1
}}

我想将此列表重塑为以下数据框:

   n1 n2   n3
1   x  a 0.18
2   x  a 0.70
3   x  a 0.57
4   x  a 0.17
5   x  a 0.94
6   x  b 0.18
7   x  b 0.70
8   x  b 0.57
9   x  b 0.17
10  x  b 0.94
11  y  a 0.18
12  y  a 0.70
13  y  a 0.57
14  y  a 0.17
15  y  a 0.94
16  y  b 0.18
17  y  b 0.70
18  y  b 0.57
19  y  b 0.17
20  y  b 0.94
21  z  a 0.18
22  z  a 0.70
23  z  a 0.57
24  z  a 0.17
25  z  a 0.94
26  z  b 0.18
27  z  b 0.70
28  z  b 0.57
29  z  b 0.17
30  z  b 0.94

我如何重塑列表?我的原始列表比上面的例子大得多。

非常感谢。

解决方法

基于

purrr::imap_dfr 的解决方案

list2 <- list(x = list(a = c(0.18,0.7,0.57,0.17,0.94),b = c(0.18,0.94)),y = list(a = c(0.18,z = list(a = c(0.18,0.94)))

library(tidyverse)
imap_dfr(list2,~.x %>% as.data.frame() %>%
           mutate(n1 = .y) %>%
           pivot_longer(!n1,names_to = 'n2',values_to = 'n3'))
#> # A tibble: 30 x 3
#>    n1    n2       n3
#>    <chr> <chr> <dbl>
#>  1 x     a      0.18
#>  2 x     b      0.18
#>  3 x     a      0.7 
#>  4 x     b      0.7 
#>  5 x     a      0.57
#>  6 x     b      0.57
#>  7 x     a      0.17
#>  8 x     b      0.17
#>  9 x     a      0.94
#> 10 x     b      0.94
#> # ... with 20 more rows

reprex package (v2.0.0) 于 2021 年 5 月 26 日创建

,

您可以将 stacklapply 结合使用,并将数据与 bind_rows 结合 -

dplyr::bind_rows(lapply(list2,stack),.id = 'n1')

#   n1 values ind
#1   x   0.18   a
#2   x   0.70   a
#3   x   0.57   a
#4   x   0.17   a
#5   x   0.94   a
#6   x   0.18   b
#7   x   0.70   b
#8   x   0.57   b
#9   x   0.17   b
#10  x   0.94   b
#11  y   0.18   a
#12  y   0.70   a
#13  y   0.57   a
#14  y   0.17   a
#15  y   0.94   a
#16  y   0.18   b
#17  y   0.70   b
#18  y   0.57   b
#19  y   0.17   b
#20  y   0.94   b
#21  z   0.18   a
#22  z   0.70   a
#23  z   0.57   a
#24  z   0.17   a
#25  z   0.94   a
#26  z   0.18   b
#27  z   0.70   b
#28  z   0.57   b
#29  z   0.17   b
#30  z   0.94   b

如果您想将其保留在基数 R 中:

data <- lapply(list2,stack)
do.call(rbind,Map(cbind,data,n1 = names(data)))
,

基本的 R 选项

setNames(
  `row.names<-`(rev(
    do.call(
      rbind,Map(stack,list2),n = names(list2)
      )
    )
  ),NULL),paste0("n",1:3)
)

给予

   n1 n2   n3
1   x  a 0.18
2   x  a 0.70
3   x  a 0.57
4   x  a 0.17
5   x  a 0.94
6   x  b 0.18
7   x  b 0.70
8   x  b 0.57
9   x  b 0.17
10  x  b 0.94
11  y  a 0.18
12  y  a 0.70
13  y  a 0.57
14  y  a 0.17
15  y  a 0.94
16  y  b 0.18
17  y  b 0.70
18  y  b 0.57
19  y  b 0.17
20  y  b 0.94
21  z  a 0.18
22  z  a 0.70
23  z  a 0.57
24  z  a 0.17
25  z  a 0.94
26  z  b 0.18
27  z  b 0.70
28  z  b 0.57
29  z  b 0.17
30  z  b 0.94
,

为什么不直接创建数据框?

names1<-c("a","b")
names2<-c("x","y","z")
b= matrix(ncol=3)[-1,]
for(i in names1)
  for(j in names2){{
    
    a<-as.data.frame(round(runif(5),2))
    a$n1 = j
    a$n2 = i
    b = rbind(b,a)
  }}
b = b[,c(2,3,1)]
colnames(b)[3]='n3'

结果如下:

   n1 n2 n3
1   x  a               0.85
2   x  a               0.98
3   x  a               0.23
4   x  a               0.44
5   x  a               0.07
6   y  a               0.66
7   y  a               0.39
8   y  a               0.84
9   y  a               0.15
10  y  a               0.35
11  z  a               0.49
12  z  a               0.15
13  z  a               0.36
14  z  a               0.96
15  z  a               0.13
16  x  b               0.01
17  x  b               0.16
18  x  b               0.81
19  x  b               0.87
20  x  b               0.51
21  y  b               0.63
22  y  b               0.84
23  y  b               0.28
24  y  b               0.67
25  y  b               0.15
26  z  b               0.98
27  z  b               0.30
28  z  b               0.12
29  z  b               0.16
30  z  b               0.94