【问题标题】:A faster (vectorized) way to create a sliding sequence of 1s and 0s with a predetermined length一种更快(矢量化)的方法来创建具有预定长度的 1 和 0 的滑动序列
【发布时间】:2019-06-17 05:00:48
【问题描述】:

我有以下功能,但我觉得有更快(矢量化或可能是包或内置?)的方式来编写它?

create_seq <- function(n, len) {
  mat <- matrix(nrow = length(0:(n-len)), ncol = n)
  for(i in 0:(n-len)) {
    mat[i + 1, ] <- c(rep(0L, i), rep(1L, len), rep(0L, n - (len + i)))
  }
  return(mat)
}

create_seq(10, 3)
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,]    1    1    1    0    0    0    0    0    0     0
#> [2,]    0    1    1    1    0    0    0    0    0     0
#> [3,]    0    0    1    1    1    0    0    0    0     0
#> [4,]    0    0    0    1    1    1    0    0    0     0
#> [5,]    0    0    0    0    1    1    1    0    0     0
#> [6,]    0    0    0    0    0    1    1    1    0     0
#> [7,]    0    0    0    0    0    0    1    1    1     0
#> [8,]    0    0    0    0    0    0    0    1    1     1
create_seq(10, 5)
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,]    1    1    1    1    1    0    0    0    0     0
#> [2,]    0    1    1    1    1    1    0    0    0     0
#> [3,]    0    0    1    1    1    1    1    0    0     0
#> [4,]    0    0    0    1    1    1    1    1    0     0
#> [5,]    0    0    0    0    1    1    1    1    1     0
#> [6,]    0    0    0    0    0    1    1    1    1     1
create_seq(7, 2)
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,]    1    1    0    0    0    0    0
#> [2,]    0    1    1    0    0    0    0
#> [3,]    0    0    1    1    0    0    0
#> [4,]    0    0    0    1    1    0    0
#> [5,]    0    0    0    0    1    1    0
#> [6,]    0    0    0    0    0    1    1

【问题讨论】:

  • 只是为了好玩,另一个选项可能是mat &lt;- matrix(1, nrow = n - len + 1, ncol = n) ; mat[col(mat) &lt; row(mat) | col(mat) &gt; (row(mat) + (len - 1))] &lt;- 0

标签: r for-loop vectorization


【解决方案1】:

创建一个稀疏带状矩阵:

library(Matrix)    

create_seq_sparse <- function(n, len) {
  bandSparse(m = n, n = n - len + 1L, k = seq_len(len) - 1L)
}

create_seq_sparse(10, 3)
# 8 x 10 sparse Matrix of class "ngCMatrix"
# 
# [1,] | | | . . . . . . .
# [2,] . | | | . . . . . .
# [3,] . . | | | . . . . .
# [4,] . . . | | | . . . .
# [5,] . . . . | | | . . .
# [6,] . . . . . | | | . .
# [7,] . . . . . . | | | .
# [8,] . . . . . . . | | |

create_seq_sparse(7, 2)
#6 x 7 sparse Matrix of class "ngCMatrix"
#
#[1,] | | . . . . .
#[2,] . | | . . . .
#[3,] . . | | . . .
#[4,] . . . | | . .
#[5,] . . . . | | .
#[6,] . . . . . | |

如果你需要一个密集的数字矩阵,你可以使用+as.matrix(...)作为最后一步。

【讨论】:

    【解决方案2】:

    函数的矢量化基 R 变体:

    create_seq <- function(n, len){
      x <- c(rep(1, len), rep(0, (n - len + 1)))
      y <- rep(x, ceiling(((n - len + 1) * n)/length(x)))
      matrix(y[1:((n - len + 1) * n)], nrow = n - len + 1, ncol = n, byrow = T)
    }
    

    这可以缩短为:

    create_seq <- function(n, len){
      matrix(rep(c(rep(1, len), rep(0, (n-len+1)))
                 , ceiling(((n-len+1)*n)/(n + 1)))[1:((n-len+1)*n)], 
             nrow = n - len + 1, ncol = n, byrow = T)
    }
    
    > create_seq(7, 4)
         [,1] [,2] [,3] [,4] [,5] [,6] [,7]
    [1,]    1    1    1    1    0    0    0
    [2,]    0    1    1    1    1    0    0
    [3,]    0    0    1    1    1    1    0
    [4,]    0    0    0    1    1    1    1
    > create_seq(5, 2)
         [,1] [,2] [,3] [,4] [,5]
    [1,]    1    1    0    0    0
    [2,]    0    1    1    0    0
    [3,]    0    0    1    1    0
    [4,]    0    0    0    1    1
    

    【讨论】:

    • 谢谢@DavidArenburg,我把它清理干净了。
    猜你喜欢
    • 2021-10-13
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    相关资源
    最近更新 更多