如何合并包含 tibbles 的列表?

How to combine lists that include tibbles?

以下是包含 tibbels 的列表:

test=list()
l <- list(list(var = "bb",b =  2, c = 3, d = 5), list(var = "a", b = 3, c  = 2,  d = 4))

l2 <- map(l,~data.frame(.))
l3 <-map_dfr(l2,~mutate_all(.,as.character))  
l4<-as_tibble(l3)
test[[1]]=l4
names(test)[1]="par"
test[[2]]=l4
names(test)[2]="mas"

myli=list()
myli[[1]]=l4
names(myli)[1]="par"
myli[[2]]=l4
names(myli)[2]="mas"

我想提取 name、var 和 d 并合并:

我需要的输出是这样的:

  var        value    list     name 
  bb         5         test    par
  a          4         test    par
  bb         5         test    mas 
  a          4         test    mas
  bb         5         myli    par
  a          4         myli    par
  bb         5         myli    mas 
  a          4         myli    mas

另一种解决方案使用 tidyr::pivot_longer

lst(myli, test) %>% 
  map_dfr(~ imap_dfr(.x, ~ .x %>% 
                       select(var,d) %>% 
                       pivot_longer(cols = var), .id = "name"), .id = "list")

# A tibble: 8 x 4
  var   list  name  value
  <chr> <chr> <chr> <chr>
1 bb    myli  par   5    
2 a     myli  par   4    
3 bb    myli  mas   5    
4 a     myli  mas   4    
5 bb    test  par   5    
6 a     test  par   4    
7 bb    test  mas   5    
8 a     test  mas   4   

您可以使用 purrr 和一些地图功能。

library(purrr)
library(tibble)
library(dplyr)

lst(test, myli) %>% 
  map_dfr(~ imap_dfr(.x, ~ add_column(.x, par = .y)), .id = "list") %>% 
  select(var, value = d, list, par)

这是将您的两个(可能更多)列表组合成一个命名列表。然后遍历每个列表。对于这些主列表中的每一个,遍历它们的子列表(par 和 mas),将元素名称添加为一列,然后堆叠结果。这为您提供了一个最终堆叠列表,您可以从中 select 您想要的变量。

# A tibble: 8 x 4
  var   value list  par  
  <chr> <chr> <chr> <chr>
1 bb    5     test  par  
2 a     4     test  par  
3 bb    5     test  mas  
4 a     4     test  mas  
5 bb    5     myli  par  
6 a     4     myli  par  
7 bb    5     myli  mas  
8 a     4     myli  mas 

编辑

受另一个解决方案的启发,我可能更喜欢这个而不是我原来的解决方案。

lst(test, myli) %>% 
  map_dfr(~ bind_rows(.x, .id = "par"), .id = "list") %>% 
  select(var, value = d, list, par)

使用 dplyr::bind_rows 你可以:

library(purrr)
library(dplyr)

map(list(test = test, myli = myli), bind_rows, .id = "name") %>% 
  bind_rows(.id = "list") %>% 
  select(var, value = d, list, name)
#> # A tibble: 8 × 4
#>   var   value list  name 
#>   <chr> <chr> <chr> <chr>
#> 1 bb    5     test  par  
#> 2 a     4     test  par  
#> 3 bb    5     test  mas  
#> 4 a     4     test  mas  
#> 5 bb    5     myli  par  
#> 6 a     4     myli  par  
#> 7 bb    5     myli  mas  
#> 8 a     4     myli  mas