假设我有一个更深的列表。我想提取特定深度的所有元素
下面是一个例子:
library(data.table)
library(purrr)
Data <- as.data.table(mtcars)
splitvariables <- c("am", "gear", "carb")
for(i in 1:length(splitvariables)){
Data <- map_depth(Data, .depth = i-1, .f = split, by = splitvariables[i])
}
现在Data
是以下(它只是它的一部分):
$`1`
$`1`$`4`
$`1`$`4`$`4`
mpg cyl disp hp drat wt qsec vs am gear carb
1: 21 6 160 110 3.9 2.620 16.46 0 1 4 4
2: 21 6 160 110 3.9 2.875 17.02 0 1 4 4
$`1`$`4`$`1`
mpg cyl disp hp drat wt qsec vs am gear carb
1: 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
2: 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
3: 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
4: 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
$`1`$`4`$`2`
mpg cyl disp hp drat wt qsec vs am gear carb
1: 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
2: 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
现在我有嵌套列表,我想要的就是绑定这些data.table
s,就像如果这些data.table
s没有那么深的深度,我会对rbindlist
做的那样。我认为必须有一个解决方案,只有一行代码?
您可以这样做:-
a <- rbindlist(unlist(unlist(Data, recursive = FALSE), recursive = FALSE))
并且a
将只是一个data.table
。
解决这个问题有两种不同的方法:
方案1:基于<<-
赋值运算符
假设data.frame
位于示例中的深度3。假设这个深度是固定的,您可以将purrr包中的map_depth
与一个匿名函数组合在一起(参见下面的fun1
内部)。每次调用匿名函数时,data.frame传递给它的对象被赋值给父环境中的列表对象l
(因此使用<<-
)。变量i
允许增加列表。
library(data.table)
library(purrr)
fun1 <- function() {
i <- 1L
l <- list()
map_depth(Data, 3, function(d) {l[[i]] <<- d; i <<- i + 1L})
rbindlist(l)
}
fun1()
# mpg cyl disp hp drat wt qsec vs am gear carb
# 1: 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# 2: 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
# 3: 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
# 4: 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
# 5: 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
# 6: 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
# 7: 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
# ...
方案二:基于递归函数
即使在包含data.frames的嵌套列表中不同分支的深度不固定,该解决方案也有效;但它要求所有最里面的列表都是data.frame(记住data.frame是一个列表对象)。另外,请注意,这个约束可以很容易地放松。在下面的代码中,while
循环中的值3
不是data.frames嵌套列表的深度,而是传递给它的典型data.frames列表的深度rbindlist
函数(例如:vec_depth(list(mtcars, mtcars))
= 3).
fun2 <- function(x) {
while(vec_depth(x) > 3) {x <- unlist(x, FALSE, FALSE); fun2(x)}
return(x)
}
rbindlist(fun2(Data))
# mpg cyl disp hp drat wt qsec vs am gear carb
# 1: 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# 2: 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
# 3: 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
# 4: 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
# 5: 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
# 6: 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
# 7: 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
# ...