提问人:umbe1987 提问时间:9/22/2023 更新时间:9/29/2023 访问量:97
生成连续和重叠的数字块序列
generate sequence of consecutive and overlapping numeric blocks
问:
由此
x <- 1:10
block.size <- 3L
我想生成一个长度为 3 的连续和重叠块序列,如下所示:
1,2,3
2,3,4
3,4,5
4,5,6
5,6,7
6,7,8
7,8,9
8,9,10
我找到了这个适用于角色的好答案。
我可以想到一个循环来做到这一点,但如果可能的话,我肯定会更喜欢更简洁和矢量化的方式。这是我的看法。
block.nums <- length(x)-len+1
blocks <- vector(mode = "list", length = block.nums)
for (i in 1:block.nums) {
blocks[[i]] <- i:(i+block.size-1)
}
答:
4赞
jpsmith
9/22/2023
#1
您可以尝试:
ll <- length(x) - (block.size - 1) # number of rows
mat <- matrix(NA, nrow = length(x) - (block.size - 1), ncol = block.size) # initiate a blank matrix
sapply(seq_len(block.size), \(xx) mat[,xx] <- x[seq_len(ll) - 1 + xx])
输出:
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 3 4
[3,] 3 4 5
[4,] 4 5 6
[5,] 5 6 7
[6,] 6 7 8
[7,] 7 8 9
[8,] 8 9 10
7赞
ThomasIsCoding
9/22/2023
#2
尝试 embed()
> embed(x, block.size)[, block.size:1]
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 3 4
[3,] 3 4 5
[4,] 4 5 6
[5,] 5 6 7
[6,] 6 7 8
[7,] 7 8 9
[8,] 8 9 10
或sequence
matrix(
sequence(
rep(1 + length(x) - block.size, block.size),
from = head(seq_along(x), block.size)
),
ncol = block.size
)
这也提供了所需的输出
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 3 4
[3,] 3 4 5
[4,] 4 5 6
[5,] 5 6 7
[6,] 6 7 8
[7,] 7 8 9
[8,] 8 9 10
评论
1赞
Mark
9/22/2023
我刚刚用 测试了这一点,你写的序列版本比最慢的答案快大约 115 倍。太棒了!x <- 1:10000 block.size <- 100
0赞
ThomasIsCoding
9/22/2023
@Mark啊哈,这是一个有趣的观察,我之前并不知道:P
1赞
umbe1987
9/22/2023
这么多很棒的答案!我决定接受这个(嵌入的),因为在我看来,这是最简洁、最直接的方法(个人喜好)。感谢您(以及所有其他提供答案的用户,+1 给大家:)
3赞
Mark
9/22/2023
#3
这是另一种方法(很可能比其他方法慢):
vapply(head(x, -block.size), \(s) seq(s, s + block.size - 1), integer(block.size)) |> t()
# Output is the same as the other ones ;)
笔记:
vapply()
与其他函数类似,但需要添加输出类型和大小。文档说它有时更快(尽管没有具体说明在哪些情况下,令人沮丧!*apply()
head()
在这种情况下,将获取除 X 的最后一个元素之外的所有内容block.size
3赞
jay.sf
9/22/2023
#4
这里有一个函数
> f <- \(n, s) {
+ stopifnot(s > 0 && s <= n)
+ if (s == 1) as.matrix(seq_len(n))
+ else t(sapply(1:(n - s + 1L), `+`, 0:(s - 1L)))
+ }
> f(10, 3)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 3 4
[3,] 3 4 5
[4,] 4 5 6
[5,] 5 6 7
[6,] 6 7 8
[7,] 7 8 9
[8,] 8 9 10
> f(5, 2)
[,1] [,2]
[1,] 1 2
[2,] 2 3
[3,] 3 4
[4,] 4 5
> f(5, 1)
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5
> f(1, 1)
[,1]
[1,] 1
> f(5, 6)
Error in f(5, 6) : s > 0 && s <= n is not TRUE
3赞
GKi
9/29/2023
#5
一种可能性是使用 .outer
outer(1:8, 0:2, `+`)
#outer(seq_len(length(x)-block.size+1), 0:(block.size-1), `+`) # Alternative with given data
# [,1] [,2] [,3]
#[1,] 1 2 3
#[2,] 2 3 4
#[3,] 3 4 5
#[4,] 4 5 6
#[5,] 5 6 7
#[6,] 6 7 8
#[7,] 7 8 9
#[8,] 8 9 10
或者具有自动重复和矢量添加功能。matrix
matrix(0:2, 8, 3, TRUE) + 1:8
# [,1] [,2] [,3]
#[1,] 1 2 3
#[2,] 2 3 4
#[3,] 3 4 5
#[4,] 4 5 6
#[5,] 5 6 7
#[6,] 6 7 8
#[7,] 7 8 9
#[8,] 8 9 10
下一个:如何在坐标列表中找到起点和终点?
评论