【问题标题】:Efficient creation of a matrix of offsets有效创建偏移矩阵
【发布时间】:2017-07-03 13:59:31
【问题描述】:

目标

我想使用一个长的数字向量来创建一个矩阵,其中每一列都是原始向量的连续偏移量(滞后或超前)。如果n 是最大偏移量,则矩阵将具有[length(vector), n * 2 + 1] 的维度(因为我们想要两个方向的偏移量,并包括0 偏移量,即原始向量)。

示例

为了说明,考虑以下向量:

test <- c(2, 8, 1, 10, 7, 5, 9, 3, 4, 6)

[1]  2  8  1 10  7  5  9  3  4  6

预期输出

现在我们创建值的偏移量,比如n == 3

      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
 [1,]   NA   NA   NA    2    8    1   10
 [2,]   NA   NA    2    8    1   10    7
 [3,]   NA    2    8    1   10    7    5
 [4,]    2    8    1   10    7    5    9
 [5,]    8    1   10    7    5    9    3
 [6,]    1   10    7    5    9    3    4
 [7,]   10    7    5    9    3    4    6
 [8,]    7    5    9    3    4    6   NA
 [9,]    5    9    3    4    6   NA   NA
[10,]    9    3    4    6   NA   NA   NA

我正在寻找一种有效的解决方案。 data.tabletidyverse 解决方案非常受欢迎。

仅返回没有NA 的行(即第 4 到第 7 行)也可以。

当前解决方案

lags  <- lapply(3:1, function(x) dplyr::lag(test, x))
leads <- lapply(1:3, function(x) dplyr::lead(test, x))
l <- c(lags, test, leads)
matrix(unlist(l), nrow = length(test))

【问题讨论】:

  • 还有library(data.table) ; data.table(test)[, c(shift(test, 3:1), shift(test, 0:3, type = "lead"))] 或者如果你想要一个没有中间步骤的矩阵,也许do.call(cbind, (c(shift(test, 3:1), shift(test, 0:3, type = "lead"))))。另见thisthis。另外,我怀疑embed 的效率,因为它在内部是一个 for 循环。如果效率真的很重要,我会做一些基准测试。
  • @DavidArenburg,在传递矩阵时似乎只有一个for 循环。对于向量的情况,我认为这是一个单一的索引调用。

标签: r


【解决方案1】:

在基数 R 中,您可以使用 embed 获取第 4 到第 7 行。但是,您必须颠倒列顺序。

embed(test, 7)[, 7:1]
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    2    8    1   10    7    5    9
[2,]    8    1   10    7    5    9    3
[3,]    1   10    7    5    9    3    4
[4,]   10    7    5    9    3    4    6

数据

test <- c(2, 8, 1, 10, 7, 5, 9, 3, 4, 6)

【讨论】:

    【解决方案2】:

    这将产生你需要的东西......

    n <- 3
    t(embed(c(rep(NA,n), test, rep(NA,n)), length(test)))[length(test):1,]
    
          [,1] [,2] [,3] [,4] [,5] [,6] [,7]
     [1,]   NA   NA   NA    2    8    1   10
     [2,]   NA   NA    2    8    1   10    7
     [3,]   NA    2    8    1   10    7    5
     [4,]    2    8    1   10    7    5    9
     [5,]    8    1   10    7    5    9    3
     [6,]    1   10    7    5    9    3    4
     [7,]   10    7    5    9    3    4    6
     [8,]    7    5    9    3    4    6   NA
     [9,]    5    9    3    4    6   NA   NA
    [10,]    9    3    4    6   NA   NA   NA
    

    【讨论】:

      【解决方案3】:

      这可以通过从一个长向量构造矩阵并仅返回所需的列和行来解决:

      test <- c(2, 8, 1, 10, 7, 5, 9, 3, 4, 6)
      n_offs <- 3L
      n_row <- length(test) + n_offs + 1L
      matrix(rep(c(rep(NA, n_offs), test), n_row), nrow = n_row)[1:length(test), 1:(n_offs * 2L + 1L)]
      
            [,1] [,2] [,3] [,4] [,5] [,6] [,7]
       [1,]   NA   NA   NA    2    8    1   10
       [2,]   NA   NA    2    8    1   10    7
       [3,]   NA    2    8    1   10    7    5
       [4,]    2    8    1   10    7    5    9
       [5,]    8    1   10    7    5    9    3
       [6,]    1   10    7    5    9    3    4
       [7,]   10    7    5    9    3    4    6
       [8,]    7    5    9    3    4    6   NA
       [9,]    5    9    3    4    6   NA   NA
      [10,]    9    3    4    6   NA   NA   NA
      

      只返回与embed(test, 7)[, 7:1] 相同结果的变体是:

      matrix(rep(test, length(test) + 1L), nrow = length(test) + 1L)[
        seq_len(length(test) - 2L * n_offs), seq_len(n_offs * 2L + 1L)]
      
           [,1] [,2] [,3] [,4] [,5] [,6] [,7]
      [1,]    2    8    1   10    7    5    9
      [2,]    8    1   10    7    5    9    3
      [3,]    1   10    7    5    9    3    4
      [4,]   10    7    5    9    3    4    6
      

      【讨论】:

        猜你喜欢
        • 2017-08-02
        • 1970-01-01
        • 1970-01-01
        • 2011-12-17
        • 1970-01-01
        • 2019-02-11
        • 1970-01-01
        • 2012-03-16
        • 2015-12-22
        相关资源
        最近更新 更多