减少/平坦r中任意层次结构的数据帧列表中的级别



我有多个数据帧列表,存储在另一个列表的列表层次结构的不同级别。我想"变平"。列表,以便只保留层次结构的最低级别。我不能使用unlist()purrr::flatten(),因为这会分解数据帧。

是否有一种简单、通用的方法来删除层次结构,并创建一个仅保留两个层次的列表(数据框架列表的列表)?


代码例子:
生成数据结构:
library(dplyr)
n <- 12
df <- lapply(1:3, function(x) {
x <- lapply(sample.int(4,n, replace = TRUE), function(y) {
ceiling(y*runif(100))}
) %>% as.data.frame()
names(x) <- letters[1:n]
return(x)
})
my_list <- lst()
for (n in 1:3) {
my_list$a[[n]] <- df[[n]][,1:3]
}
for (n in 1:3) {
my_list$b$c[[n]] <- df[[n]][,4:6]
}
for (n in 1:3) {
my_list$a$b$d$e[[n]] <- df[[n]][,7:9]
}
my_list %>% str()
我想要的工作代码:
lst(
a = my_list$a[1:3],
b = my_list$a$b$d$e,
c = my_list$b$c

) %>% str()

输出:
多层分层结构:
List of 2
$ a:List of 4
..$  :'data.frame':   100 obs. of  3 variables:
.. ..$ a: num [1:100] 2 1 1 1 1 1 2 2 2 1 ...
.. ..$ b: num [1:100] 1 1 1 2 2 1 2 2 2 2 ...
.. ..$ c: num [1:100] 2 1 1 2 1 1 1 2 1 2 ...
..$  :'data.frame':   100 obs. of  3 variables:
.. ..$ a: num [1:100] 2 2 1 1 2 1 3 3 1 3 ...
.. ..$ b: num [1:100] 1 1 3 2 3 1 3 3 3 3 ...
.. ..$ c: num [1:100] 1 2 2 1 3 2 4 3 3 1 ...
..$  :'data.frame':   100 obs. of  3 variables:
.. ..$ a: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ b: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ c: num [1:100] 2 2 1 1 1 1 1 1 1 2 ...
..$ b:List of 1
.. ..$ d:List of 1
.. .. ..$ e:List of 3
.. .. .. ..$ :'data.frame':   100 obs. of  3 variables:
.. .. .. .. ..$ g: num [1:100] 3 3 1 3 1 1 1 3 1 2 ...
.. .. .. .. ..$ h: num [1:100] 1 1 2 1 1 1 1 2 1 1 ...
.. .. .. .. ..$ i: num [1:100] 1 1 2 2 2 1 1 2 2 1 ...
.. .. .. ..$ :'data.frame':   100 obs. of  3 variables:
.. .. .. .. ..$ g: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. .. .. .. ..$ h: num [1:100] 2 4 4 4 3 3 3 2 4 4 ...
.. .. .. .. ..$ i: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. .. .. ..$ :'data.frame':   100 obs. of  3 variables:
.. .. .. .. ..$ g: num [1:100] 2 1 3 2 3 1 1 2 1 2 ...
.. .. .. .. ..$ h: num [1:100] 1 2 1 2 1 1 1 1 1 2 ...
.. .. .. .. ..$ i: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
$ b:List of 1
..$ c:List of 3
.. ..$ :'data.frame': 100 obs. of  3 variables:
.. .. ..$ d: num [1:100] 2 2 2 1 1 1 2 1 1 1 ...
.. .. ..$ e: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. .. ..$ f: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ :'data.frame': 100 obs. of  3 variables:
.. .. ..$ d: num [1:100] 1 2 2 2 1 2 2 2 1 1 ...
.. .. ..$ e: num [1:100] 1 2 2 1 2 1 1 1 2 2 ...
.. .. ..$ f: num [1:100] 2 2 1 1 1 2 2 1 1 1 ...
.. ..$ :'data.frame': 100 obs. of  3 variables:
.. .. ..$ d: num [1:100] 2 3 3 1 3 4 4 4 1 3 ...
.. .. ..$ e: num [1:100] 1 2 2 1 1 1 3 2 3 3 ...
.. .. ..$ f: num [1:100] 3 3 3 3 1 2 2 2 3 1 ...
期望的输出,一个两级链表结构:
List of 3
$ a:List of 3
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ a: num [1:100] 2 1 1 1 1 1 2 2 2 1 ...
.. ..$ b: num [1:100] 1 1 1 2 2 1 2 2 2 2 ...
.. ..$ c: num [1:100] 2 1 1 2 1 1 1 2 1 2 ...
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ a: num [1:100] 2 2 1 1 2 1 3 3 1 3 ...
.. ..$ b: num [1:100] 1 1 3 2 3 1 3 3 3 3 ...
.. ..$ c: num [1:100] 1 2 2 1 3 2 4 3 3 1 ...
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ a: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ b: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ c: num [1:100] 2 2 1 1 1 1 1 1 1 2 ...
$ b:List of 3
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ g: num [1:100] 3 3 1 3 1 1 1 3 1 2 ...
.. ..$ h: num [1:100] 1 1 2 1 1 1 1 2 1 1 ...
.. ..$ i: num [1:100] 1 1 2 2 2 1 1 2 2 1 ...
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ g: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ h: num [1:100] 2 4 4 4 3 3 3 2 4 4 ...
.. ..$ i: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ g: num [1:100] 2 1 3 2 3 1 1 2 1 2 ...
.. ..$ h: num [1:100] 1 2 1 2 1 1 1 1 1 2 ...
.. ..$ i: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
$ c:List of 3
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ d: num [1:100] 2 2 2 1 1 1 2 1 1 1 ...
.. ..$ e: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ f: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ d: num [1:100] 1 2 2 2 1 2 2 2 1 1 ...
.. ..$ e: num [1:100] 1 2 2 1 2 1 1 1 2 2 ...
.. ..$ f: num [1:100] 2 2 1 1 1 2 2 1 1 1 ...
..$ :'data.frame':    100 obs. of  3 variables:
.. ..$ d: num [1:100] 2 3 3 1 3 4 4 4 1 3 ...
.. ..$ e: num [1:100] 1 2 2 1 1 1 3 2 3 3 ...
.. ..$ f: num [1:100] 3 3 3 3 1 2 2 2 3 1 ...

一种选择是将列表平铺为数据帧列表,然后将其拆分为数据帧列表的列表

flatten <- function(x) {
while (any(vapply(x, inherits, logical(1L), 'list'))) {
x <- lapply(x, function(xx)
if (inherits(xx, 'list'))
xx else list(xx))
x <- unlist(x, recursive = FALSE)
}
x
}
fl <- flatten(my_list)
str(split(fl, gsub('\d+$', '', names(fl))))

我不知道如何使用标准的平坦化函数实现这一点,但是设计一个可以做到这一点的算法非常简单。您只需遍历嵌套列表的结构,并只保留那些没有其他列表的列表作为子列表。

find_last_lists <- function(lst, parent.names=NULL) {

# return 'lst' if it has no items that are lists
if (!any(sapply(lst, is.list))) {

setNames(list(lst), 
parent.names[[length(parent.names)-1]])

# otherwise go through all items recursively 
} else {

df.list <- NULL
for (i in seq_along(lst)) {

df.list <- c(df.list, 
find_last_lists(lst[[i]], 
c(parent.names, list(names(lst)[i]))))
}

df.list
}
}

它基本上是对树的深度优先遍历,我使用了递归函数(也可以使用非递归解决方案)。parent.names存储父列表项的名称顺序。

fl <- find_last_lists(my_list)
# List of 9
# $ a:'data.frame': 100 obs. of  3 variables:
#   ..$ a: num [1:100] 3 2 2 2 1 3 1 3 1 2 ...
#   ..$ b: num [1:100] 3 3 1 2 2 1 3 3 2 2 ...
#   ..$ c: num [1:100] 2 1 1 2 4 1 2 3 3 3 ...
# $ a:'data.frame': 100 obs. of  3 variables:
#   ..$ a: num [1:100] 1 1 1 1 1 1 1 2 2 2 ...
#   ..$ b: num [1:100] 2 4 4 2 1 1 2 3 3 4 ...
#   ..$ c: num [1:100] 1 1 3 3 2 1 2 3 1 3 ...
# $ a:'data.frame': 100 obs. of  3 variables:
#   ..$ a: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
#   ..$ b: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
#   ..$ c: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
# $ e:'data.frame': 100 obs. of  3 variables:
#   ..$ g: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
#   ..$ h: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
#   ..$ i: num [1:100] 1 2 2 1 1 1 1 1 2 2 ...
# $ e:'data.frame': 100 obs. of  3 variables:
#   ..$ g: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
#   ..$ h: num [1:100] 1 2 2 1 1 2 2 2 1 1 ...
#   ..$ i: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
# $ e:'data.frame': 100 obs. of  3 variables:
#   ..$ g: num [1:100] 1 1 2 1 2 2 3 3 3 2 ...
#   ..$ h: num [1:100] 2 1 1 1 2 2 1 2 2 2 ...
#   ..$ i: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
# $ c:'data.frame': 100 obs. of  3 variables:
#   ..$ d: num [1:100] 2 1 3 3 3 4 4 4 3 3 ...
#   ..$ e: num [1:100] 2 3 3 3 3 3 3 2 3 3 ...
#   ..$ f: num [1:100] 4 1 1 1 2 1 2 4 4 3 ...
# $ c:'data.frame': 100 obs. of  3 variables:
#   ..$ d: num [1:100] 4 1 1 3 4 4 4 4 4 2 ...
#   ..$ e: num [1:100] 4 3 4 2 4 4 2 4 2 4 ...
#   ..$ f: num [1:100] 3 1 2 2 2 1 3 3 2 3 ...
# $ c:'data.frame': 100 obs. of  3 variables:
#   ..$ d: num [1:100] 1 1 4 3 3 1 1 2 2 1 ...
#   ..$ e: num [1:100] 2 1 1 3 3 1 1 1 1 3 ...
#   ..$ f: num [1:100] 1 3 2 2 4 4 1 3 3 2 ...

结果是一个数据帧列表,这些数据帧可以进一步分组并重新排序为您所需的格式,如下所示:

fl <- tapply(fl, names(fl), unname)
fl <- fl[order(names(fl))]

最新更新