生成连续和重叠的数字块序列

generate sequence of consecutive and overlapping numeric blocks

提问人:umbe1987 提问时间:9/22/2023 更新时间:9/29/2023 访问量:97

问:

由此

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)
}
R 序列

评论

0赞 Mark 9/22/2023
这些数字按递增顺序对您来说重要吗?我在你的例子中看到它们是,但在你的描述中你没有提到这一点

答:

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 ;)

笔记:

  1. vapply()与其他函数类似,但需要添加输出类型和大小。文档说它有时更快(尽管没有具体说明在哪些情况下,令人沮丧!*apply()
  2. 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