【问题标题】:Converting a nested (3-level) list to a long/tall format data frame将嵌套(3 级)列表转换为长/高格式数据框
【发布时间】:2019-07-10 23:02:45
【问题描述】:

我有一个包含 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

对于try1 和try2 中的每个子列表,我需要提取suit 子列表并rbind 其元素,以使生成的数据框为具有4 列的长格式-value(的值花色),suit(标识价值来自哪个花色,即菱形或梅花),iter(标识花色属于哪个子列表,即 1 或 2)和 try(try1 或 try2) .

我可以使用expand.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]])

结果:

> 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

但是,我想知道是否有更通用/更简洁的方法来重现上述结果(最好在基 R 中)?我正在考虑从每个子列表中提取西装元素,然后使用像stack() 这样递归地出现在结果列表中:

rapply(m, function(x) setNames(stack(x), names(x)))

但这会引发错误,我不太清楚为什么,也不知道用什么代替它。

【问题讨论】:

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


    【解决方案1】:

    我们可以使用map 和melt 的组合

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

    或者enframe和map

    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
    

    【讨论】:

    • rapply 根本不可能,是吗?
    • @jay.sf 首先,需要提取嵌套在里面的“西装”。这就是我使用map 的原因
    • 谢谢@akrun!我花了很长时间试图弄清楚这一点,所以我很感激你的帮助。我只是想知道为什么sublist = m %&gt;% map(pluck, "suit") 不能单独工作? sublist = modify_depth(m, 2, "suit") 工作,但 pluck(m, "suit") 返回 NULL。
    • 因为modify_depth 2 是从嵌套列表中提取,而map(pluck 是在第一级寻找“西装”
    猜你喜欢
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 2020-06-22
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    相关资源
    最近更新 更多