提问人:John J. 提问时间:10/24/2023 最后编辑:John J. 更新时间:10/25/2023 访问量:69
从嵌套列表的每个元素中删除特定值
remove specific values from each element of a nested list
问:
我有一个嵌套列表,如下所示:
nested.list <- list(c(46270L, 103154L, 159944L, 193405L, 199925L), c(24049L,
30454L, 55710L, 106407L, 122059L, 174131L), c(14520L, 46270L,
153636L, 188626L, 199925L), c(8150L, 24049L, 27321L, 30461L,
33513L, 55710L, 58933L, 71342L, 103154L, 122059L, 159920L, 169516L,
174131L), c(19195L, 71333L, 122059L, 137645L, 153636L, 183740L,
195065L, 199925L), c(14520L, 60368L, 80939L, 82381L, 95070L,
103172L, 106379L, 147215L, 166353L, 199925L), c(30461L, 68324L,
75981L, 77674L, 106407L, 120284L), c(24029L, 72751L, 103154L,
120284L, 142359L))
> nested.list
[[1]]
[1] 46270 103154 159944 193405 199925
[[2]]
[1] 24049 30454 55710 106407 122059 174131
[[3]]
[1] 14520 46270 153636 188626 199925
[[4]]
[1] 8150 24049 27321 30461 33513 55710 58933 71342 103154 122059 159920 169516 174131
[[5]]
[1] 19195 71333 122059 137645 153636 183740 195065 199925
[[6]]
[1] 14520 60368 80939 82381 95070 103172 106379 147215 166353 199925
[[7]]
[1] 30461 68324 75981 77674 106407 120284
[[8]]
[1] 24029 72751 103154 120284 142359
在每个列表中,我只想保留这些数字。(经过编辑以包括更具说明性的列表)。
target.values <- c(24029, 33513, 60368, 106407, 147215, 153636, 159920, 193405)
我试过了,但显然我错过了一些关于它如何工作的东西。purrr::keep(.x = nested.list, .p = function(x){all(x %in% target.values)})
答:
1赞
Till
10/24/2023
#1
purrr::keep()
在您的示例中,以顶级列表为目标。以嵌套为目标
我们需要用列表/向量来遍历列表,即 或。lapply()
purrr::map()
您的示例列表不包含任何目标值,因此我撒了一些
在我的例子中。nested.list
library(purrr)
map(nested.list, keep, \(x) x %in% target.values)
#> [[1]]
#> [1] 33514
#>
#> [[2]]
#> [1] 193406
#>
#> [[3]]
#> integer(0)
#>
#> [[4]]
#> [1] 60369 193406
#>
#> [[5]]
#> integer(0)
#>
#> [[6]]
#> [1] 193406 60369
#>
#> [[7]]
#> [1] 106408
#>
#> [[8]]
#> [1] 106408
3赞
Michael M
10/24/2023
#2
仅仅因为一个对象被调用,它就必然是一个嵌套列表。You 对象是一个向量列表,我们不需要特殊的包:nested.list
lapply(nested.list, function(z) z[z %in% target.values])
评论
2赞
thelatemail
10/24/2023
事实上。如果它实际上是嵌套的,那么你需要递归搜索 -rapply(nested.list, \(z) z[z %in% target.values], how="list")
4赞
Onyambu
10/24/2023
#3
您可以使用:intersect
lapply(nested.list,intersect, target.values)
2赞
ThomasIsCoding
10/24/2023
#4
以下是不同实现的基准测试
set.seed(0)
nested.list <- replicate(1000, sample.int(100, sample.int(100, 1)))
target.values <- sample.int(100, 50)
f1 <- function() {
lapply(nested.list, \(x) x[x %in% target.values])
}
f2 <- function() {
lapply(nested.list, intersect, target.values)
}
f3 <- function() {
Map(intersect, nested.list, list(target.values))
}
f4 <- function() {
rapply(nested.list, \(z) z[z %in% target.values], how = "list")
}
f5 <- function() {
map(nested.list, keep, \(x) x %in% target.values)
}
microbenchmark(
f1 = f1(),
f2 = f2(),
f3 = f3(),
f4 = f4(),
f5 = f5(),
unit = "relative",
check = "equivalent",
times = 50L
)
这给了
Unit: relative
expr min lq mean median uq max neval
f1 1.0000000 1.000000 1.000000 1.000000 1.000000 1.000000 50
f2 4.1351785 4.099845 4.127982 4.088224 4.117141 3.649927 50
f3 4.2296240 4.291979 4.842893 4.408095 4.817794 13.234459 50
f4 0.9750334 0.979558 1.097199 1.010855 1.085660 1.760977 50
f5 71.8225616 69.069376 64.921864 67.952181 64.960019 47.465078 50
我们可以看到,或者 with 应该是最有效的方式,而效率最低。lapply
rapply
%in%
keep
3赞
jblood94
10/24/2023
#5
您可以对比较进行矢量化,以便为具有大量向量的列表提供一些加速。
f6 <- function(x, target) {
u <- unlist(x)
i <- which(u %in% target)
setNames(split(u[i], rep(as.factor(1:length(x)), lengths(x))[i]), names(x))
}
使用 @ThomasIsCoding 的基准测试:
microbenchmark::microbenchmark(
f1 = f1(),
f2 = f2(),
f6 = f6(nested.list, target.values),
unit = "relative",
check = "equivalent"
)
#> Unit: relative
#> expr min lq mean median uq max neval
#> f1 2.106476 1.893394 2.113900 1.895352 1.883364 3.380201 100
#> f2 6.219841 5.649225 6.325568 5.629023 5.760277 6.345773 100
#> f6 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100
评论