从深层嵌套列表中提取数据

时间:2020-11-06 19:52:21

标签: r purrr

考虑这个复杂的嵌套示例(无论是否相信它在我的数据集中都是真实的)

> nestedlist <- list(list('fakedata' = 'hello',
+                    list(list('name'= list('john','litz'), 'age'= 30))),
+                    list('fakedata' = 'there',
+                    list(list('name'= list('frank','doe'), 'age'= 34))))
> 
> nestedlist %>% str
List of 2
 $ :List of 2
  ..$ fakedata: chr "hello"
  ..$         :List of 1
  .. ..$ :List of 2
  .. .. ..$ name:List of 2
  .. .. .. ..$ : chr "john"
  .. .. .. ..$ : chr "litz"
  .. .. ..$ age : num 30
 $ :List of 2
  ..$ fakedata: chr "there"
  ..$         :List of 1
  .. ..$ :List of 2
  .. .. ..$ name:List of 2
  .. .. .. ..$ : chr "frank"
  .. .. .. ..$ : chr "doe"
  .. .. ..$ age : num 34

我正在尝试使用purrr从中提取元素。提取fakedata字段之类的简单操作很容易:

> purrr::map(nestedlist, 'fakedata')
[[1]]
[1] "hello"

[[2]]
[1] "there"

但是,我对name字段感兴趣。在这种情况下,我的purrr解决方案不起作用:

> purrr::map(nestedlist, list(1,1,'name')) 
[[1]]
NULL

[[2]]
NULL

这里是什么问题? 谢谢!

2 个答案:

答案 0 :(得分:1)

我本来建议使用purrr::pluck(),然后通读文档,发现您实际上可以只使用purrr::map()

您非常接近:您需要将访问器列表传递给map()而不是字符向量,并且您错过了一个访问器。

nestedlist %>% map( list('data', 1, 'name') )

[[1]]
[[1]][[1]]
[1] "john"

[[1]][[2]]
[1] "litz"


[[2]]
[[2]][[1]]
[1] "frank"

[[2]][[2]]
[1] "doe"

答案 1 :(得分:1)

另一种选择是在rrapply()软件包(基础rrapply的扩展名)中使用rapply(),正是为此目的而制作的:

library(rrapply)   ## v1.2.1

## filter 'name' nodes as flat list
str(rrapply(nestedlist, classes = "list", condition = function(x, .xname) .xname == "name", how = "flatten"))
#> List of 2
#>  $ name:List of 2
#>   ..$ : chr "john"
#>   ..$ : chr "litz"
#>  $ name:List of 2
#>   ..$ : chr "frank"
#>   ..$ : chr "doe"


## prune 'name' nodes maintaining list structure
str(rrapply(nestedlist, classes = "list", condition = function(x, .xname) .xname == "name", how = "prune"))
#> List of 2
#>  $ :List of 1
#>   ..$ :List of 1
#>   .. ..$ :List of 1
#>   .. .. ..$ name:List of 2
#>   .. .. .. ..$ : chr "john"
#>   .. .. .. ..$ : chr "litz"
#>  $ :List of 1
#>   ..$ :List of 1
#>   .. ..$ :List of 1
#>   .. .. ..$ name:List of 2
#>   .. .. .. ..$ : chr "frank"
#>   .. .. .. ..$ : chr "doe"