2017-05-03 4 views
3

다음과 비슷한 대각선을 따라 값이있는 일부 대형 행렬로 작업하고 있습니다.R - 행렬 대각선을 따라 길이가 '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 
     ) 

대각선의 세그먼트를 연결하기 위해 길이 'n'이하의 데이터 간격을 채우고 싶습니다. 예를 들어, 상기 매트릭스를 이용하고 3 이하의 데이터 갭 충진 I이로부터 이동하고자 :

diag_indx <- which(!is.na(ontrack), arr.ind=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 

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

을주는 인스턴스가 newV 인 경우 결과는 (2,2) 또는 (3,2) 일 수 있습니다. 후속 코드는 diag_indx 행렬을 사용하지만 더 효율적인 경우 데이터 갭을 ontrack 행렬에 직접 채울 수 있습니다 (모든 값 사용). 해결책을 해결하려고 노력에서

, 나는이 sequence length equation

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)]) 
} 

를 사용하여 diag_indx 매트릭스의 데이터 격차를 찾는 상상하고 seq()을 사용하여 데이터 격차를 작성했다. 모든 것을 효율적으로 조합하는 방법을 모르겠습니다. 도와 줘서 고마워.

답변

1

일부 시행 착오 끝에 기본 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))} 
    } 
} 

그리고

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 
위의 diag_indx에서 테스트