R-填写长度为'的数据空白;n';或者沿着矩阵对角线
我正在处理一些大型矩阵,这些矩阵的值沿对角线分布,如下所示R-填写长度为'的数据空白;n';或者沿着矩阵对角线,r,matrix,missing-data,diagonal,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,N
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
)
对此
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
矩阵中填补数据空白(使用任何值都可以)
在试图找出解决方案时,我设想使用以下方法在diag\u indx
矩阵中查找数据缺口
seqle经过反复试验,我想出了一个(不太漂亮)的解决方案,它只需要基本的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))}
}
}
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
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)])
}
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))}
}
}
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