将嵌套(三级)列表转换为长/高格式数据帧

时间:2019-02-17 10:44:19

标签: r list data-manipulation nested-lists melt

我有一个包含3个级别的嵌套列表:

m = list(try1 = list(list(court = c("jack", "queen", "king"),
                          suit = list(diamonds = 2, clubs = 5)), 
                     list(court = c("jack", "queen", "king"),
                          suit = list(diamonds = 45, clubs = 67))), 
         try2 = list(list(court = c("jack", "queen", "king"),
                          suit = list(diamonds = 400, clubs = 300)), 
                     list(court = c("jack", "queen", "king"),
                          suit = list(diamonds = 5000, clubs = 6000))))

> str(m)
List of 2
 $ try1:List of 2
  ..$ :List of 2
  .. ..$ court: chr [1:3] "jack" "queen" "king"
  .. ..$ suit :List of 2
  .. .. ..$ diamonds: num 2
  .. .. ..$ clubs   : num 5
  ..$ :List of 2
  .. ..$ court: chr [1:3] "jack" "queen" "king"
  .. ..$ suit :List of 2
  .. .. ..$ diamonds: num 45
  .. .. ..$ clubs   : num 67
 $ try2:List of 2
  ..$ :List of 2
  .. ..$ court: chr [1:3] "jack" "queen" "king"
  .. ..$ suit :List of 2
  .. .. ..$ diamonds: num 400
  .. .. ..$ clubs   : num 300
  ..$ :List of 2
  .. ..$ court: chr [1:3] "jack" "queen" "king"
  .. ..$ suit :List of 2
  .. .. ..$ diamonds: num 5000
  .. .. ..$ clubs   : num 6000

对于try1try2中的每个子列表,我需要提取suit子列表并重新绑定其元素,以使结果数据帧采用4列的长格式-{ {1}}(西装的价值),value(标识该西装的价值来自哪个钻石或球杆),suit(标识该西装属于哪个子列表,即1或2)和iter(try1或try2)。

我可以结合使用tryexpand.grid()

mapply()

结果:

grd = expand.grid(try = names(m), iter = 1:2, suit = c("diamonds", "clubs"))

grd$value = mapply(function(x, y, z) m[[x]][[y]]$suit[[z]], grd[[1]], grd[[2]], grd[[3]])

但是,我想知道是否有一种更通用/更简洁的方式来再现上述结果(最好在基数R中)?我正在考虑从每个子列表中提取出西服元素,然后使用在结果列表中递归类似> grd try iter suit value 1 try1 1 diamonds 2 2 try2 1 diamonds 400 3 try1 2 diamonds 45 4 try2 2 diamonds 5000 5 try1 1 clubs 5 6 try2 1 clubs 300 7 try1 2 clubs 67 8 try2 2 clubs 6000 之类的内容:

stack()

但这会引发错误,我不确定为什么,而且我不知道该用什么代替。

1 个答案:

答案 0 :(得分:2)

我们可以结合使用mapmelt

library(purrr)
library(reshape2)
library(dplyr)
map_df(m, ~ .x %>%
                 map(pluck, "suit")  %>% 
                   melt, .id = 'try') 

或者使用enframemap

library(tibble)
map_df(m, ~ .x %>% 
              map_df(pluck, "suit") %>% 
                    map_df(~ enframe(.x, name = "iter") %>%
                       unnest, .id = "suit"), .id = 'try'  )
# A tibble: 8 x 4
#  try   suit      iter value
#  <chr> <chr>    <int> <dbl>
#1 try1  diamonds     1     2
#2 try1  diamonds     2    45
#3 try1  clubs        1     5
#4 try1  clubs        2    67
#5 try2  diamonds     1   400
#6 try2  diamonds     2  5000
#7 try2  clubs        1   300
#8 try2  clubs        2  6000