R(purrr)展平命名列表以列出并保留名称 [英] R (purrr) flatten list of named lists to list and keep names
问题描述
也许我遗漏了一些明显的东西,但试图将R中的命名列表的命名列表的列表(甚至可能更多地嵌套)展平为最终一个展平列表. purrr
和 rlist
似乎都有相应的工具.我如何才能实现子列表的名称成为平坦结果列表的名称预加密,例如 purrr
中的 list1.blist.a
?我的实际列表更深入地嵌套了不同数量的级别,并在不同级别上重复了名称.最后,我执行 purrr :: map_df(final_list,bind_rows)
,这似乎删除了所有重复的名称(即使我不知道原来的重复名称来自哪个分支,从).我可以使用 rlist
来做到这一点,但我一直希望有一个 tidyverse
解决方案(没有什么能与出色的 rlist
媲美的,但是很多人已经有了 tidyverse 代码>).
Maybe I'm missing something obvious but trying to flatten a list of named lists of named lists in R (may even be more nested) into eventually one flat list. purrr
and rlist
seem to have tools for that. How can I achieve that names of sublists become name precrypts of flattened result list, e.g. list1.blist.a
in purrr
? My actual list is more deeply nested with varying number of levels and repeating names on different levels. In the end I perform purrr::map_df(final_list, bind_rows)
and this seems to drop all duplicate names (and even if it didn't I don't know from which branch the original duplicate name comes from). I can do it with rlist
but I had hoped for a tidyverse
solution (nothing against fantastic rlist
but many already have tidyverse
installed).
还请注意, rlist :: list.flatten()
会始终删除除顶部之外的所有级别,而 purrr :: flatten()
会一次删除一级有时可能是您所需要的.您可以根据需要多次嵌套purrr :: map(.x,.f = rlist :: list.flatten)来实现相同的目的,但这很麻烦并且不美观/不可读.
Also note that rlist::list.flatten()
will always remove all levels but the top while purrr::flatten()
drops levels one at a time which may sometimes be what you need. You could achieve the same by nesting purrr::map(.x, .f = rlist::list.flatten) as often as you require but it's cumbersome and not beautiful/readable.
alist <- list(list1 = list(a = 1, b = 2, blist = list(a = 3, b = 4)),
list2 = list(a = 1, b = 2, blist = list(a = 3, b = 4)))
str(alist)
List of 2
$ list1:List of 3
..$ a : num 1
..$ b : num 2
..$ blist:List of 2
.. ..$ a: num 3
.. ..$ b: num 4
$ list2:List of 3
..$ a : num 1
..$ b : num 2
..$ blist:List of 2
.. ..$ a: num 3
.. ..$ b: num 4
alist_flat <- purrr::map(alist, purrr::flatten)
str(alist_flat)
List of 2
$ list1:List of 4
..$ a: num 1
..$ b: num 2
..$ a: num 3
..$ b: num 4
$ list2:List of 4
..$ a: num 1
..$ b: num 2
..$ a: num 3
..$ b: num 4
alist_flattest <- purrr::flatten(alist_flat)
str(alist_flattest)
List of 8
$ a: num 1
$ b: num 2
$ a: num 3
$ b: num 4
$ a: num 1
$ b: num 2
$ a: num 3
$ b: num 4
# works with rlist
alist_flat_names <- map(alist, rlist::list.flatten, use.names = TRUE)
str(alist_flat_names)
List of 2
$ list1:List of 4
..$ a : num 1
..$ b : num 2
..$ blist.a: num 3
..$ blist.b: num 4
$ list2:List of 4
..$ a : num 1
..$ b : num 2
..$ blist.a: num 3
..$ blist.b: num 4
alist_flattest_names <- rlist::list.flatten(alist_flat_names, use.names = TRUE)
str(alist_flattest_names)
List of 8
$ list1.a : num 1
$ list1.b : num 2
$ list1.blist.a: num 3
$ list1.blist.b: num 4
$ list2.a : num 1
$ list2.b : num 2
$ list2.blist.a: num 3
$ list2.blist.b: num 4
推荐答案
我查看了rlist :: list.flatten()的源代码,并将源代码复制到一个新函数中以避免这种依赖性.
I looked at the source for rlist::list.flatten() and copied the source into a new function to avoid that dependency.
my_flatten <- function (x, use.names = TRUE, classes = "ANY")
{
#' Source taken from rlist::list.flatten
len <- sum(rapply(x, function(x) 1L, classes = classes))
y <- vector("list", len)
i <- 0L
items <- rapply(x, function(x) {
i <<- i + 1L
y[[i]] <<- x
TRUE
}, classes = classes)
if (use.names && !is.null(nm <- names(items)))
names(y) <- nm
y
}
alist <- list(list1 = list(a = 1, b = 2, blist = list(a = 3, b = 4)),
list2 = list(a = 1, b = 2, blist = list(a = 3, b = 4)))
flat_list <- my_flatten(alist)
str(flat_list)
结果:
List of 8
$ list1.a : num 1
$ list1.b : num 2
$ list1.blist.a: num 3
$ list1.blist.b: num 4
$ list2.a : num 1
$ list2.b : num 2
$ list2.blist.a: num 3
$ list2.blist.b: num 4
这篇关于R(purrr)展平命名列表以列出并保留名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!