取消列出嵌套列表的倒数第二个列表
Unlist the second to last list of a nested list
我有一个深度嵌套的列表列表。在嵌套列表的“中心”是一个包含 n 整数的向量。我需要计算每个嵌套列表中有多少整数,然后 unlist 上面的一个级别以获得这些计数的向量(即,我想要 c(0, 5, 0, 0, 3)
,而不是嵌套中心的 list(0, 1:5, 0, 0, 1:3)
。
这看起来相对简单 - 我能够使用 rapply
来完成第一部分,即将 list(0, 1:5, 0, 0, 1:3)
转换为 list(0, 5, 0, 0, 3)
。 我的具体问题我需要帮助的是如何取消列出最里面的列表到向量(而不是 list(0, 5, 0, 0, 3)
我想要 c(0, 5, 0, 0, 3)
我搜索并尝试了各种 apply
、lapply
、unlist
方法,但其中 none 非常正确,因为它们针对的是最里面的列表。由于我要取消列出的列表是倒数第二个元素,我正在努力寻找一种优雅地完成此操作的方法。
在下面的示例数据中,我可以通过两种方式获得所需的结果:多个 lapply
函数或 for
循环。但是,我的实际数据包含更多列表和数百万个数据点,因此这些可能不是有效的选择。
以下是 (1) 示例数据,(2) 我尝试过的,以及 (3) 具有所需结构的示例数据。
示例数据
have_list <- list(scenario1 = list(method1 = list(place1 = list(0, 1:5, 0, 0, 1:3),
place2 = list(1:2, 0, 1:10, 0, 0),
place3 = list(0:19, 0, 0, 0, 0),
place4 = list(1:100, 0, 0, 1:4, 0)),
method2 = list(place1 = list(1:5, 1:5, 0, 0, 1:3),
place2 = list(0, 0, 1:5, 0, 0),
place3 = list(0:19, 0, 1:7, 0, 0),
place4 = list(1:22, 0, 0, 1:4, 0)),
method3 = list(place1 = list(0, 1:2, 1:6, 0, 1:3),
place2 = list(1:2, 0, 1:6, 1:4, 0),
place3 = list(0:19, 0, 0, 0, 1:2),
place4 = list(1:12, 0, 0, 1:12, 0))),
scenario2 = list(method1 = list(place1 = list(0, 1:5, 0, 0, 1:3),
place2 = list(1:2, 0, 1:10, 0, 0),
place3 = list(0:19, 0, 0, 0, 0),
place4 = list(1:100, 0, 0, 1:4, 0)),
method2 = list(place1 = list(1:5, 1:5, 0, 0, 1:3),
place2 = list(0, 0, 1:5, 0, 0),
place3 = list(0:19, 0, 1:7, 0, 0),
place4 = list(1:22, 0, 0, 1:4, 0)),
method3 = list(place1 = list(0, 1:2, 1:6, 0, 1:3),
place2 = list(1:2, 0, 1:6, 1:4, 0),
place3 = list(0:19, 0, 0, 0, 1:2),
place4 = list(1:12, 0, 0, 1:12, 0))))
我试过的
还有我访问过的问题:
- R - unlist nested list of dates
- Issues unlisting a nested-list
# Get number of integers in each nested list
lengths <- rapply(have_list, function(x) unlist(length(x)), how = "list") # this works fine
#' Each count is currently still in its own list of length 1,
#' Convert each count to vector
#' In the "middle" the nested list:
# I have list(0, 5, 0, 0, 3)
# I want c(0, 5, 0, 0, 3)
# Attempts to unlist the counts
# Unlist the counts
test1 <- rapply(lengths, unlist, how = "list") # doesn't work
test2 <- unlist(lengths, recursive = FALSE) # doesn't work
test3 <- lapply(lengths, function(x) lapply(x, unlist)) # doesnt work
test4 <- lapply(lengths, function(x) lapply(x, unlist, recursive = FALSE)) # doesnt work
test5 <- rapply(have_list, function(x) unlist(length(x)), how = "list") #doesnt work
test6 <- rapply(have_list, function(x) unlist(length(x)), how = "unlist") #doesnt work
我想要的数据结构
# This works on test data but is impractical for real data
want_list <- lapply(lengths, function(w) lapply(w, function(x) lapply(x, unlist)))
# or
want_list <- lengths
## for loops work but is not practical
for (i in 1:length(lengths)){
for (j in 1:length(lengths[[i]])){
for (k in 1:length(lengths[[i]][[j]])){
want_list[[i]][[j]][[k]] <- unlist(lengths[[i]][[j]][[k]])
}
}
}
一个选项是 melt
嵌套的 list
和 rrapply
,用 lengths
替换 'value' 列,然后使用递归拆分 ( rsplit
) 来自 collapse
library(rrapply)
library(collapse)
dat <- transform(rrapply(have_list, how = "melt"), value= lengths(value))
out <- rsplit(dat$value, dat[1:3])
-预期使用 OP 进行测试
identical(out, want_list)
[1] TRUE
这可以通过使用递归来完成。一个简单的递归将是:
my_fun <- function(x) if(is.list(x[[1]])) lapply(x, my_fun) else lengths(x)
out <- my_fun(have_list)
identical(out, want_list)
[1] TRUE
使用 rrapply()
的另一种解决方案可能是使用 condition
函数将 lengths()
仅应用于向量列表:
library(rrapply)
out <- rrapply(have_list, classes = "list", condition = \(x) is.numeric(x[[1]]), f = lengths)
identical(want_list, out)
#> [1] TRUE
我有一个深度嵌套的列表列表。在嵌套列表的“中心”是一个包含 n 整数的向量。我需要计算每个嵌套列表中有多少整数,然后 unlist 上面的一个级别以获得这些计数的向量(即,我想要 c(0, 5, 0, 0, 3)
,而不是嵌套中心的 list(0, 1:5, 0, 0, 1:3)
。
这看起来相对简单 - 我能够使用 rapply
来完成第一部分,即将 list(0, 1:5, 0, 0, 1:3)
转换为 list(0, 5, 0, 0, 3)
。 我的具体问题我需要帮助的是如何取消列出最里面的列表到向量(而不是 list(0, 5, 0, 0, 3)
我想要 c(0, 5, 0, 0, 3)
我搜索并尝试了各种 apply
、lapply
、unlist
方法,但其中 none 非常正确,因为它们针对的是最里面的列表。由于我要取消列出的列表是倒数第二个元素,我正在努力寻找一种优雅地完成此操作的方法。
在下面的示例数据中,我可以通过两种方式获得所需的结果:多个 lapply
函数或 for
循环。但是,我的实际数据包含更多列表和数百万个数据点,因此这些可能不是有效的选择。
以下是 (1) 示例数据,(2) 我尝试过的,以及 (3) 具有所需结构的示例数据。
示例数据
have_list <- list(scenario1 = list(method1 = list(place1 = list(0, 1:5, 0, 0, 1:3),
place2 = list(1:2, 0, 1:10, 0, 0),
place3 = list(0:19, 0, 0, 0, 0),
place4 = list(1:100, 0, 0, 1:4, 0)),
method2 = list(place1 = list(1:5, 1:5, 0, 0, 1:3),
place2 = list(0, 0, 1:5, 0, 0),
place3 = list(0:19, 0, 1:7, 0, 0),
place4 = list(1:22, 0, 0, 1:4, 0)),
method3 = list(place1 = list(0, 1:2, 1:6, 0, 1:3),
place2 = list(1:2, 0, 1:6, 1:4, 0),
place3 = list(0:19, 0, 0, 0, 1:2),
place4 = list(1:12, 0, 0, 1:12, 0))),
scenario2 = list(method1 = list(place1 = list(0, 1:5, 0, 0, 1:3),
place2 = list(1:2, 0, 1:10, 0, 0),
place3 = list(0:19, 0, 0, 0, 0),
place4 = list(1:100, 0, 0, 1:4, 0)),
method2 = list(place1 = list(1:5, 1:5, 0, 0, 1:3),
place2 = list(0, 0, 1:5, 0, 0),
place3 = list(0:19, 0, 1:7, 0, 0),
place4 = list(1:22, 0, 0, 1:4, 0)),
method3 = list(place1 = list(0, 1:2, 1:6, 0, 1:3),
place2 = list(1:2, 0, 1:6, 1:4, 0),
place3 = list(0:19, 0, 0, 0, 1:2),
place4 = list(1:12, 0, 0, 1:12, 0))))
我试过的
还有我访问过的问题:
- R - unlist nested list of dates
- Issues unlisting a nested-list
# Get number of integers in each nested list
lengths <- rapply(have_list, function(x) unlist(length(x)), how = "list") # this works fine
#' Each count is currently still in its own list of length 1,
#' Convert each count to vector
#' In the "middle" the nested list:
# I have list(0, 5, 0, 0, 3)
# I want c(0, 5, 0, 0, 3)
# Attempts to unlist the counts
# Unlist the counts
test1 <- rapply(lengths, unlist, how = "list") # doesn't work
test2 <- unlist(lengths, recursive = FALSE) # doesn't work
test3 <- lapply(lengths, function(x) lapply(x, unlist)) # doesnt work
test4 <- lapply(lengths, function(x) lapply(x, unlist, recursive = FALSE)) # doesnt work
test5 <- rapply(have_list, function(x) unlist(length(x)), how = "list") #doesnt work
test6 <- rapply(have_list, function(x) unlist(length(x)), how = "unlist") #doesnt work
我想要的数据结构
# This works on test data but is impractical for real data
want_list <- lapply(lengths, function(w) lapply(w, function(x) lapply(x, unlist)))
# or
want_list <- lengths
## for loops work but is not practical
for (i in 1:length(lengths)){
for (j in 1:length(lengths[[i]])){
for (k in 1:length(lengths[[i]][[j]])){
want_list[[i]][[j]][[k]] <- unlist(lengths[[i]][[j]][[k]])
}
}
}
一个选项是 melt
嵌套的 list
和 rrapply
,用 lengths
替换 'value' 列,然后使用递归拆分 ( rsplit
) 来自 collapse
library(rrapply)
library(collapse)
dat <- transform(rrapply(have_list, how = "melt"), value= lengths(value))
out <- rsplit(dat$value, dat[1:3])
-预期使用 OP 进行测试
identical(out, want_list)
[1] TRUE
这可以通过使用递归来完成。一个简单的递归将是:
my_fun <- function(x) if(is.list(x[[1]])) lapply(x, my_fun) else lengths(x)
out <- my_fun(have_list)
identical(out, want_list)
[1] TRUE
使用 rrapply()
的另一种解决方案可能是使用 condition
函数将 lengths()
仅应用于向量列表:
library(rrapply)
out <- rrapply(have_list, classes = "list", condition = \(x) is.numeric(x[[1]]), f = lengths)
identical(want_list, out)
#> [1] TRUE