我正在寻找一种快速的解决方案,用于随机地从嵌套在列表中的向量中进行子集抽样。
如果我们模拟以下数据,将得到一个包含 300 万个向量的列表l
,每个向量的长度为 5。但是,我希望每个向量的长度各不相同。所以,我想应用一个函数来随机地对每个向量进行子集抽样。问题是,这种方法不如我所希望的那样快速。
模拟数据:列表l
library(stringi)
set.seed(123)
vec_n <- 15e6
vec_vals <- 1:vec_n
vec_names <- stringi::stri_rand_strings(vec_n, 5)
my_named_vec <- setNames(vec_vals, vec_names)
split_func <- function(x, n) {
unname(split(x, rep_len(1:n, length(x))))
}
l <- split_func(my_named_vec, n = vec_n / 5)
head(l)
#> [[1]]
#> HmPsw Qk8NP Quo3T 8f0GH nZmjN
#> 1 3000001 6000001 9000001 12000001
#>
#> [[2]]
#> 2WtYS ZaHFl 6YjId jbGuA tAG65
#> 2 3000002 6000002 9000002 12000002
#>
#> [[3]]
#> xSgZ6 jM5Uw ujPOc CTV5F 5JRT5
#> 3 3000003 6000003 9000003 12000003
#>
#> [[4]]
#> tF2Kx r4ZCI Ooklo VOLHU M6z6H
#> 4 3000004 6000004 9000004 12000004
#>
#> [[5]]
#> tgdze w8d1B FYERK jlClo NQfsF
#> 5 3000005 6000005 9000005 12000005
#>
#> [[6]]
#> hXaH9 gsY1u CjBwC Oqqty dxJ4c
#> 6 3000006 6000006 9000006 12000006
现在我们有了l
,我希望可以随机地对每个向量进行子集操作:也就是说,被子集化的元素数量(每个向量)将是随机的。因此,一种选项是设置以下实用函数:
randomly_subset_vec <- function(x) {
my_range <- 1:length(x)
x[-sample(my_range, sample(my_range))]
}
lapply(head(l), randomly_subset_vec)
#> [[1]]
#> Quo3T
#> 6000001
#>
#> [[2]]
#> 6YjId jbGuA
#> 6000002 9000002
#>
#> [[3]]
#> xSgZ6 jM5Uw ujPOc CTV5F
#> 3 3000003 6000003 9000003
#>
#> [[4]]
#> Ooklo
#> 6000004
#>
#> [[5]]
#> named integer(0)
#>
#> [[6]]
#> CjBwC Oqqty dxJ4c
#> 6000006 9000006 12000006
但是在整个l
上运行这个过程需要很长时间。我尝试使用rrapply
,它是一个用于处理列表的快速包,在我的机器上只需 "110" 秒。
library(rrapply)
library(tictoc)
tic()
l_subsetted <- rrapply(object = l, f = randomly_subset_vec)
toc()
#> 110.23 sec elapsed
我很乐意做以下任何一件事:
- Is there a speedier alternative to:
rrapply(object = l, f = randomly_subset_vec)
- Or more generally, is there a speedier way to start with
my_named_vec
and arrive atl_subsetted
?
reprex()
运行了代码,但仍然没有得到相同的结果。你能否也尝试使用reprex()
运行一下? - Emmanvec_n <- 15e3
时,我得到了正确的字母数字名称,但是当vec_n <- 15e6
时,这些名称被数字替换了。除了stringi
之外,我没有安装任何其他包。我的 R 版本是 4.1.1。Windows 10 PC。 - Emman