在子集化后将包含索引号的列表列表映射到标准索引序列
Mapping a list of lists containing index numbers to a standard index sequence after subsetting
我正在使用一个由三个级别分层的数据结构。例如,假设我的结构 D 是
First Second Third Value Index (let's do 1-indexing)
1 1 1 a 1
1 1 2 a 2
1 1 3 a 3
1 2 1 a 4
1 2 2 a 5
2 1 1 a 6
2 1 2 a 7
我形成了一个嵌套列表结构来索引对应于每个分组结构的组件:
[[1]]
[[1]][[1]]
1 2 3
[[1]][[2]]
4 5
[[2]]
[[2]][[1]]
6 7
实际上,我的结构 D 是巨大的,在我的上下文中,我将对 D 的随机子集执行操作。我进行随机子集化的方式是对每个不同水平进行分层抽样。例如,假设第一个级别包含 1:1000,第二个级别包含 1:100,第三个级别包含 1:50。我可能会对 50 个第一级标识符、10 个二级标识符和 3 个第三级标识符进行子采样,这可能会给我类似的东西(调用下面的嵌套结构 A(
[[1]]
[[1]][[1]]
2 27 49
[[1]][[2]]
61 80 95
....
[[1]][[10]]
2409 3509 5609
[[2]]
[[2]][[1]]
7092 8091 9039
...
在基于上述索引的子集化之后,比如现在使用结构 D',D' 的索引不再是上面的索引,而是(称为下面的嵌套结构 A'(
[[1]]
[[1]][[1]]
1 2 3
[[1]][[2]]
4 5 6
....
[[1]][[10]]
28 29 30
[[2]]
[[2]][[1]]
31 32 33
...
将 A 映射到 A' 的最有效方法是什么?这样做效率会很好,因为看起来我会多次执行此操作,并且可能是我整个程序中的速率限制步骤。我目前正在使用 Rcpp (C++(,并且可能某些子集小于所需的采样数(例如,一些二级索引可能小于 10,例如 7,在这种情况下,我们只采用所有 7 个标签(。
在直接进入Rcpp
之前,我鼓励您考虑如何在基础R
中做到这一点。列表、子集化和索引是基础R
的基础,可以非常有效。
下面,我们有一个解决您问题的解决方案。您会注意到,它可能更有效,但就目前而言,这是非常简单的方法,并且易于理解。稍后我们将测试效率,然后解决任何问题。
A_prime <- function(A) {
## Generate index vector for all of A
ind <- seq_len(sum(unlist(lapply(A, lengths))))
## Generate the ending index of each vector
endInd <- cumsum(lengths(unlist(A, recursive = F)))
## Use the endInd to create the corresponding start index
startInd <- c(1L, endInd[-length(endInd)] + 1L)
## Create a simple list with the appropriate index vector
A_ind <- mapply(function(s, e) ind[s:e], startInd, endInd, SIMPLIFY = FALSE)
## Again, using the structure of A, we begin creating starting
## and ending indices to replicate the structure of A
A_end <- cumsum(lengths(A))
A_strt <- c(1L, A_end[-length(A_end)] + 1L)
## Create the desired result
lapply(seq_along(A), function(x) A_ind[A_strt[x]:A_end[x]])
}
让我们在 OP 提出的类似问题上对其进行测试:
set.seed(35)
a <- sort(sample(10000, 60))
L1 <- lapply(seq.int(1, 60, 3), function(x) {
a[x:(x + 2)]
})
A <- list(L1[1:10], L1[11:20])
str(A)
List of 2
$ :List of 10
..$ : int [1:3] 4 203 205
..$ : int [1:3] 710 1281 1515
..$ : int [1:3] 1605 1784 1846
..$ : int [1:3] 1904 1993 2425
..$ : int [1:3] 2468 2499 2630
..$ : int [1:3] 2910 2920 3210
..$ : int [1:3] 3360 3464 3469
..$ : int [1:3] 3689 3811 4002
..$ : int [1:3] 4053 4304 4358
..$ : int [1:3] 4433 5290 5862
$ :List of 10
..$ : int [1:3] 6017 6021 6155
..$ : int [1:3] 6250 6370 6414
..$ : int [1:3] 6447 6530 6656
..$ : int [1:3] 6706 6820 6977
..$ : int [1:3] 6986 7148 7338
..$ : int [1:3] 7515 7522 7666
..$ : int [1:3] 7755 7889 7891
..$ : int [1:3] 8071 8143 8487
..$ : int [1:3] 8625 8731 8945
..$ : int [1:3] 8957 9149 9770
这是输出:
str(A_prime(A))
List of 2
$ :List of 10
..$ : int [1:3] 1 2 3
..$ : int [1:3] 4 5 6
..$ : int [1:3] 7 8 9
..$ : int [1:3] 10 11 12
..$ : int [1:3] 13 14 15
..$ : int [1:3] 16 17 18
..$ : int [1:3] 19 20 21
..$ : int [1:3] 22 23 24
..$ : int [1:3] 25 26 27
..$ : int [1:3] 28 29 30
$ :List of 10
..$ : int [1:3] 31 32 33
..$ : int [1:3] 34 35 36
..$ : int [1:3] 37 38 39
..$ : int [1:3] 40 41 42
..$ : int [1:3] 43 44 45
..$ : int [1:3] 46 47 48
..$ : int [1:3] 49 50 51
..$ : int [1:3] 52 53 54
..$ : int [1:3] 55 56 57
..$ : int [1:3] 58 59 60
这看起来还不错!函数A_prime
的一个好处是嵌套列表不必是统一的。让我们在一个包含超过 10Mb 数据的非常大的列表上测试一下:
set.seed(123)
big_ind <- sort(sample(1e8, 1e6))
## generate random chunks
endIndBig <- sort(sample(1e6, 1e5))
startIndBig <- c(1L, endIndBig)
endIndBig <- c(endIndBig, 1e6)
A_big_init <- mapply(function(s, e) big_ind[s:e], startIndBig, endIndBig, SIMPLIFY = FALSE)
## generate random chunks for nested lists
A_big_ends <- sort(sample(length(A_big_init), 1e3))
A_big_strts <- c(1L, A_big_ends)
A_big_ends <- c(A_big_ends, length(A_big_init))
A_big <- lapply(seq_along(A_big_ends), function(x) A_big_init[A_big_strts[x]:A_big_ends[x]])
以下是有关A_big
的一些摘要信息。如您所见,每个子列表的长度并不统一:
print(object.size(A_big), units = "Mb")
# 10.7 Mb
length(A_big)
# [1] 1001
head(lengths(A_big))
# [1] 159 175 59 69 175 38
tail(lengths(A_big))
# [1] 88 4 225 91 74 59
A_big[[1]][[1]]
# [1] 3 72 722 836 929 1014 1091 1127
A_big[[1]][[159]]
# [1] 170285 170370 170482 170763 170793 170913 170965 171066 171240 171397 171464 171572 171590 171722
# [15] 171898 171903 172196 172284 172298 172590 172696 172698
A_big[[1000]][[2]]
# [1] 99856337 99856415
A_big[[1000]][[74]]
# [1] 99938669 99938699 99938743 99939158 99939664 99939803
现在,对于关键时刻...
system.time(A_prime(A_big))
user system elapsed
0.201 0.003 0.203
A_big_prime <- A_prime(A_big)
A_big_prime[[1]][[1]]
# [1] 1 2 3 4 5 6 7 8
A_big_prime[[1]][[159]]
# [1] 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898
# [21] 1899 1900
A_big_prime[[1000]][[2]]
# [1] 1109671 1109672
A_big_prime[[1000]][[74]]
# [1] 1110583 1110584 1110585 1110586 1110587 1110588
这还不错!!如我们所见,映射都是使用基本R
正确快速地执行的。
- 跟随整数索引列表的自定义类迭代器
- 在子集化后将包含索引号的列表列表映射到标准索引序列
- CLI/C++dataGridView示例-设置comobox单元格列表的索引
- 对C++列表的基于索引的访问
- 存储将单个查询图像与多个图像的列表匹配的关键点索引
- C++娜娜 如何从全局列表框*指针访问列表框内的索引 0 上的按钮?
- 在索引中插入节点:链接列表未正确返回列表
- 如何在C 中以给定索引列表中的项目插入项目
- 获得给定向量的排列索引列表的最佳方法是什么?
- 列表和向量的索引之间的差异
- 图像中使用CUDA中的白色像素索引列表
- 如何获得具有多个索引的对象列表
- 用eCmascript Regex验证Python列表索引语法
- 将元素从一个向量复制到另一个向量的最有效方法,给定一个不被复制的索引列表
- 获取类型列表中的类型的索引
- 如何存储或生成2d索引列表
- 使用纹理,法线和索引列表从VBO绘制OpenGL对象的问题
- 对数字及其索引列表进行排序的最快方法
- 为什么数组的索引/列表不以 1 开头?
- C++数据结构来执行索引列表