从R中的列表列表构建数据帧的最佳方法

时间:2018-02-04 12:43:53

标签: r list

我有一个子列表列表,我希望将其转换为数据帧(特别是作为tibble);例如:

myList <- list(
        list(var1=1,var2=2,var3=3,var4=4,var5=5,var6=6),
        list(var1=4,var2=5,var3=6,var4=7,var5=8,var6=9),
        list(var1=7,var2=8,var3=9,var4=1,var5=2,var6=3)
)

使用以下代码,我可以将所选变量提取到一个tibble数据框

myDF <- tbl_df(cbind(
  var1 = lapply(myList, '[[', "var1"),
  var2 = lapply(myList, '[[', "var2"),
  var5 = lapply(myList, '[[', "var5"),
  var6 = lapply(myList, '[[', "var6")
))  

但它非常冗长。是否有更简洁的方法(可能使用purrr map函数),可以从每个列表中提取所选的子元素并将它们填充到一行中?

此外,如果子列表本身包含列表,那么如何最好地提取这些列表的元素; e.g:

 myList <- list(
        list(var1=1,var2=2,var3=3,list4=list(varA="a",varB="b")),
        list(var1=4,var2=5,var3=6,list4=list(varA="c",varB="d")),
        list(var1=7,var2=8,var3=9,list4=list(varA="e",varB="f"))
)    

我怎样才能得到以下内容:

myDF <- tbl_df(cbind(
  var1 = lapply(myList, '[[', "var1"),
  var2 = lapply(myList, '[[', "var2"),
  var4 = lapply(myList, '[[', "list4$varA")
)) 

我想从列表4中提取特定元素,但使用$表示法向下钻取到下一级别不起作用?

2 个答案:

答案 0 :(得分:4)

由于数据框只是列表,如果您的列表不是多次嵌套。

library(tidyverse)
myList %>%
  map(as.data.frame) %>%
  bind_rows() %>%
  select(var1, var2, var5, var6)

#    var1 var2 var5 var6
# 1    1    2    5    6
# 2    4    5    8    9
# 3    7    8    2    3

甚至以下情况,bind_rows()实际上都适用于列表列表。

myList %>%
  bind_rows() %>%
  select(var1, var2, var5, var6)

#    var1  var2  var5  var6
#    <dbl> <dbl> <dbl> <dbl>
# 1  1.00  2.00  5.00  6.00
# 2  4.00  5.00  8.00  9.00
# 3  7.00  8.00  2.00  3.00

但有时可能会出现这样的情况:每个列表元素只有一些共同的元素,而您只想选择那些

myList %>%
  map(as.data.frame) %>%
  map(~ select(.x, var1, var2, var5, var6)) %>%
  bind_rows()

#    var1 var2 var5 var6
# 1    1    2    5    6
# 2    4    5    8    9
# 3    7    8    2    3

对于使用flatten()

中的purrr进行多次嵌套调查的情况
myList2 <- list(
  list(var1=1,var2=2,var3=3,list4=list(varA="a",varB="b")),
  list(var1=4,var2=5,var3=6,list4=list(varA="c",varB="d")),
  list(var1=7,var2=8,var3=9,list4=list(varA="e",varB="f"))
)  

myList2 %>%
  map(flatten) %>%
  bind_rows()

#   var1  var2  var3 varA  varB 
#   <dbl> <dbl> <dbl> <chr> <chr>
# 1  1.00  2.00  3.00 a     b    
# 2  4.00  5.00  6.00 c     d    
# 3  7.00  8.00  9.00 e     f  

并根据需要应用select(),名称将是相应元素的名称。请注意不同元素中的重复名称,因为它只需要一个。

可能会出现enframe() tibble函数也很有用的情况。

答案 1 :(得分:0)

对于第一种情况,可能的基础R解决方案:

> data.frame(do.call(rbind, myList))[c("var1", "var2", "var5", "var5")]
var1 var2 var5 var6
1    1    2    5    6
2    4    5    8    9
3    7    8    2    3