R - 沿矩阵对角线填充长度为 'n' 或更短的数据间隙

标签 r matrix missing-data diagonal

我正在处理一些大型矩阵,其值沿对角线类似于以下内容。

ontrack <- matrix(c(
         runif(1),NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         runif(1),NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,runif(1),NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,runif(1),runif(1),NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,runif(1),NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
         NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,runif(1)),
         nrow=14, byrow=T
         )

我想填充长度为“n”或更短的数据间隙以连接对角线段。例如使用上面的矩阵并填充 3 或更少的数据间隙,我想从这个开始:

diag_indx <- which(!is.na(ontrack), arr.ind=T)

给出

     row col
[1,]   1   1
[2,]   2   1
[3,]   3   3
[4,]   7   5
[5,]   7   6
[6,]   9   8
[7,]  14  13

对此

     row col
       1   1
       2   1
 newV  3   2
       3   3
  new  4   4
  new  5   4
  new  6   4
       7   5
       7   6
  new  8   7
       9   8
      14  13

对于像 newV 这样的实例,结果可以是 (2,2) 或 (3,2)。我的后续代码使用 diag_indx 矩阵,但如果效率更高,可以直接在 ontrack 矩阵中填充数据间隙(使用任何值都可以)。

在尝试制定解决方案时,我设想使用此 sequence length equation 查找 diag_indx 矩阵中的数据间隙

seqle <- function(x, incr=1) { 
  if(!is.integer(x)) x <- as.integer(x) 
  n <- length(x)  
  y <- x[-1L] != x[-n] + incr 
  i <- c(which(y|is.na(y)),n) 
  list(lengths = diff(c(0L,i)),
       values = x[head(c(0L,i)+1L,-1L)]) 
}

然后使用 seq() 填充数据空白。我只是不确定如何有效地将它们组合在一起。感谢您的帮助。

最佳答案

经过反复试验,我想出了一个(不太漂亮)只需要基本 R 函数的解决方案。

diagFillSeq <- function(diag_indx, fillgap=1){
  repeat{
    for(cols in 1:2){
      diag_indx <- diag_indx[order(diag_indx[, cols]), ] #Sort by selected column
      repeat{
        diffs <- diff(diag_indx[, cols]) 
        #Find breaks in sequence with differences >1 (diffs==1 are in sequence) and less than or equal to fillgap
        gap_indx <- which(diffs > 1 & diffs <= (fillgap +1)) #need +1 because fencepost error: 3rd & 7th post diffs=4 but fillgap=3)
        if(length(gap_indx) == 0){break}
        insert_indx <- gap_indx[1]
        seq_length <- diffs[gap_indx[1]] - 1  #need -1 because fencepost error
        #Subset diag_indx and insert filling sequence
        diag_indx <- rbind(diag_indx[1:insert_indx, ],
                      cbind(
                        as.integer( seq(from=diag_indx[insert_indx, 1] +1, to=diag_indx[insert_indx+1, 1] -1, length.out=seq_length) ),
                        as.integer( seq(from=diag_indx[insert_indx, 2] +1, to=diag_indx[insert_indx+1, 2] -1, length.out=seq_length) ) 
                      ),
                      diag_indx[(insert_indx+1):nrow(diag_indx), ]) 
      }
    }
    #Recheck first column to see if any new sequence gaps were created
    diffs <- diff(diag_indx[, 1])
    gap_indx <- which(diffs > 1 & diffs <= (fillgap +1))
    if(length(gap_indx) == 0){return(unname(diag_indx))}
  }
}

并对上面的 diag_indx 进行测试

whatIwant <- matrix(as.integer(c(1,2,3,3,4,5,6,7,7,8,9,14, 1,1,2,3,4,4,4,5,6,7,8,13)), ncol=2)
whatIwant
#      [,1] [,2]
# [1,]    1    1
# [2,]    2    1
# [3,]    3    2
# [4,]    3    3
# [5,]    4    4
# [6,]    5    4
# [7,]    6    4
# [8,]    7    5
# [9,]    7    6
#[10,]    8    7
#[11,]    9    8
#[12,]   14   13

identical(diagFillSeq(diag_indx, fillgap=3), whatIwant)
#TRUE

关于R - 沿矩阵对角线填充长度为 'n' 或更短的数据间隙,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43767235/

相关文章:

返回 NaN 而不是 -1

r - dplyr 中的 group_by 日期列

r - 如何选择 R 矩阵中的唯一列

Python:从列表创建协方差矩阵

algorithm - 有没有一种快速的方法来在 Matlab 中反转矩阵?

r - R STAN 中的 Bernoulli Prior

python - 如何使用python处理时间序列中股票价格的连续缺失值?

使用 dplyr 将多行中的值按列类别重组为单行

r - 如果通常的 `t( )` 不起作用,如何在 r 中转置矩阵?

python - 如何在 cython 中使用 unordered_map?