显然有很多关于这个主题的问题,但我看不出任何一般的解决方案:我有一个深度递归的列表,并希望将其展平为包含所有非列表项的单个列表
例如,请使用此嵌套列表:
d = list(
list(
list(
iris[sample(1:150,3),],
iris[sample(1:150,3),]
),
list(
list(
iris[sample(1:150,3),],
list(
iris[sample(1:150,3),],
iris[sample(1:150,3),]
)
)
)
)
)
把它变成这个:
list(iris[sample(1:150,3),],
iris[sample(1:150,3),],
iris[sample(1:150,3),],
iris[sample(1:150,3),],
iris[sample(1:150,3),])
我根据其他解决方案尝试了以下一些方法:
purrr::flatten(d)
plyr::llply(d, unlist)
lapply(d, unlist, use.names=FALSE)
无达到期望的结果,在该示例中是单个列表长度5,所有项目都是data.frame
。任何建议表示赞赏。
答案 0 :(得分:9)
这是仅使用基数R的一般展平函数:
flatten <- function(x) {
if (!inherits(x, "list")) return(list(x))
else return(unlist(c(lapply(x, flatten)), recursive = FALSE))
}
结果:
flatten(d)
#[[1]]
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#44 5.0 3.5 1.6 0.6 setosa
#138 6.4 3.1 5.5 1.8 virginica
#87 6.7 3.1 4.7 1.5 versicolor
#
#[[2]]
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#19 5.7 3.8 1.7 0.3 setosa
#1 5.1 3.5 1.4 0.2 setosa
#71 5.9 3.2 4.8 1.8 versicolor
#
#[[3]]
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#31 4.8 3.1 1.6 0.2 setosa
#98 6.2 2.9 4.3 1.3 versicolor
#134 6.3 2.8 5.1 1.5 virginica
#
#[[4]]
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#140 6.9 3.1 5.4 2.1 virginica
#119 7.7 2.6 6.9 2.3 virginica
#57 6.3 3.3 4.7 1.6 versicolor
#
#[[5]]
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#73 6.3 2.5 4.9 1.5 versicolor
#54 5.5 2.3 4.0 1.3 versicolor
#146 6.7 3.0 5.2 2.3 virginica
类似地:
x <- list(list("A"), list(list("A"), list("A")))
flatten(x)
#[[1]]
#[1] "A"
#
#[[2]]
#[1] "A"
#
#[[3]]
#[1] "A"
x <- list(list(1), list(list(2), list(3)))
flatten(x)
#[[1]]
#[1] 1
#
#[[2]]
#[1] 2
#
#[[3]]
#[1] 3
当目标是删除更多列表时,似乎有点过时了,但list
/ unlist
路由是连接具有不同数量元素的列表的唯一可靠方法。
答案 1 :(得分:5)
rlang::squash
非常神奇:
set.seed(47)
d = list(list(list(iris[sample(1:150,3),],
iris[sample(1:150,3),]),
list(list(iris[sample(1:150,3),],
list(iris[sample(1:150,3),],
iris[sample(1:150,3),])
))
))
rlang::squash(d)
#> [[1]]
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 147 6.3 2.5 5.0 1.9 virginica
#> 56 5.7 2.8 4.5 1.3 versicolor
#> 113 6.8 3.0 5.5 2.1 virginica
#>
#> [[2]]
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 124 6.3 2.7 4.9 1.8 virginica
#> 86 6.0 3.4 4.5 1.6 versicolor
#> 103 7.1 3.0 5.9 2.1 virginica
#>
#> [[3]]
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 59 6.6 2.9 4.6 1.3 versicolor
#> 70 5.6 2.5 3.9 1.1 versicolor
#> 81 5.5 2.4 3.8 1.1 versicolor
#>
#> [[4]]
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 139 6.0 3.0 4.8 1.8 virginica
#> 21 5.4 3.4 1.7 0.2 setosa
#> 104 6.3 2.9 5.6 1.8 virginica
#>
#> [[5]]
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 25 4.8 3.4 1.9 0.2 setosa
#> 90 5.5 2.5 4.0 1.3 versicolor
#> 75 6.4 2.9 4.3 1.3 versicolor
答案 2 :(得分:3)
您的数据:
d <- list(
list(
list(
iris[sample(1:150,3),],
iris[sample(1:150,3),]
),
list(
list(
iris[sample(1:150,3),],
list(
iris[sample(1:150,3),],
iris[sample(1:150,3),]
)
)
)
)
)
首先,一个粗略但有效的功能:
f <- function(x) {
if (is.null(x)) return
n <- length(x)
if (length(n) == 0) return
for (i in 1:n) {
if (is.data.frame(x[[i]])) {
res <<- append(res, list(x[[i]]))
} else {
if (is.list(x[[i]])) {
f(x[[i]])
}
}
}
}
粗略但有效的伴随全局变量:
res <- list()
f(d)
结果:
res
## [[1]]
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 37 5.5 3.5 1.3 0.2 setosa
## 16 5.7 4.4 1.5 0.4 setosa
## 8 5.0 3.4 1.5 0.2 setosa
##
## [[2]]
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 10 4.9 3.1 1.5 0.1 setosa
## 141 6.7 3.1 5.6 2.4 virginica
## 86 6.0 3.4 4.5 1.6 versicolor
##
## [[3]]
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 134 6.3 2.8 5.1 1.5 virginica
## 40 5.1 3.4 1.5 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
##
## [[4]]
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 33 5.2 4.1 1.5 0.1 setosa
## 132 7.9 3.8 6.4 2.0 virginica
## 76 6.6 3.0 4.4 1.4 versicolor
##
## [[5]]
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 10 4.9 3.1 1.5 0.1 setosa
## 16 5.7 4.4 1.5 0.4 setosa
## 135 6.1 2.6 5.6 1.4 virginica
较少原油(无全局变量)解决方案:
f2 <- function(x) {
res <- list()
if (is.null(x)) return
n <- length(x)
if (length(n) == 0) return
for (i in 1:n) {
if (is.data.frame(x[[i]])) {
res <- append(res, list(x[[i]]))
} else {
if (is.list(x[[i]])) res <- append(res, f2(x[[i]]))
}
}
return(res)
}
f2(d)
## same output
答案 3 :(得分:1)
rrapply
是rapply
的概括,可以将嵌套列表展平为叶子列表。 dfaslist=FALSE
将导致数据帧被视为叶子,而不是被递归到其中。
library(rrapply)
rrapply(d, f = identity, dfaslist = FALSE, how = "flatten")