2017-01-18 29 views
10

我正在嘗試編寫一個R代碼以返回矩陣中最大的連續數字對。連續的對可以是水平的,垂直的和兩個對角線。R:返回矩陣中最大的連續數字對

例如 如果我有矩陣:

ma = array(c(8,4,3,1,7,5,9,15,6,10,16,11,2,14,12,13), dim = c(4,4)) 

最高連續對爲(1)的水平:16和12; (2)垂直:16和11(3)對角線():16和13;和(4)對角線(/):16和15.

我如何在R中做到這一點?

+3

單曲< - 毫安[1:3,] +毫安[2:4,];其中(s == max(s),arr.ind = TRUE)'獲得行對中第一對的索引;它的對將直接在它下面。對於列,您可以翻轉逗號。對角線將會有更多的工作。 – alistaire

+1

對角線應該是s < - ma [1:3,1:3] + ma [2:4,2:4]; (s == max(s),arr.ind = TRUE)'不是? – BonStats

+0

你正在尋找最大的連續配對?否則,你如何比較對? – C8H10N4O2

回答

1

這是一個使用矩陣算法的解決方案,它將比行和列上的嵌套循環更有效,其中,尤其是在大型矩陣上。

directionalSums <- function(x){ 
    stopifnot(is.matrix(x)) 

    # padding functions to allow matrix addition 
    padL <- function(x) cbind(-Inf,x) 
    padR <- function(x) cbind(x,-Inf) 
    padU <- function(x) rbind(-Inf,x) 
    padD <- function(x) rbind(x,-Inf) 

    # these padding functions are just for readability 
    padLU <- function(x) padL(padU(x)) 
    padLD <- function(x) padL(padD(x)) 
    padRU <- function(x) padR(padU(x)) 
    padRD <- function(x) padR(padD(x)) 

    m <- nrow(x) 
    n <- ncol(x) 

    sumR <- padR((padL(x) + padR(x))[1:m,2:n]) 
    sumD <- padD((padU(x) + padD(x))[2:m,1:n]) 
    sumRD <- padRD((padLU(x) + padRD(x))[2:m,2:n]) 
    sumRU <- padRU((padRU(x) + padLD(x))[2:m,2:n]) 

    list(`right`=sumR, 
     `down`=sumD, 
     `right and down`=sumRD, 
     `right and up`=sumRU) 

} 

讓我們試試吧。

(sumList <- directionalSums(ma)) 

maxLocList <- lapply(sumList, function(x) which(x==max(x), arr.ind=TRUE)) 

for (i in 1:length(maxLocList)){ 
    nameD <- names(maxLocList)[i] 
    startCell <- maxLocList[[i]] 
    maxSum <- sumList[[i]][startCell] 
    x1 <- ma[startCell] 
    x2 <- maxSum - x1 
    writeLines(paste0('The max-sum consec. pair going ', 
        nameD, ' starts at [', 
        paste(startCell, collapse=', '), 
        '], with sum ', maxSum, 
        ' and components ', x1, ' and ',x2) 
      ) 
} 

返回:

$right 
    [,1] [,2] [,3] [,4] 
[1,] 15 13 8 -Inf 
[2,] 9 15 24 -Inf 
[3,] 12 25 28 -Inf 
[4,] 16 26 24 -Inf 

$down 
    [,1] [,2] [,3] [,4] 
[1,] 12 12 16 16 
[2,] 7 14 26 26 
[3,] 4 24 27 25 
[4,] -Inf -Inf -Inf -Inf 

$`right and down` 
    [,1] [,2] [,3] [,4] 
[1,] 13 17 20 -Inf 
[2,] 13 21 22 -Inf 
[3,] 18 20 29 -Inf 
[4,] -Inf -Inf -Inf -Inf 

$`right and up` 
    [,1] [,2] [,3] [,4] 
[1,] -Inf -Inf -Inf -Inf 
[2,] 11 11 12 -Inf 
[3,] 8 19 30 -Inf 
[4,] 10 31 23 -Inf 

The max-sum consec. pair going right starts at [3, 3], with sum 28 and components 16 and 12 
The max-sum consec. pair going down starts at [3, 3], with sum 27 and components 16 and 11 
The max-sum consec. pair going right and down starts at [3, 3], with sum 29 and components 16 and 13 
The max-sum consec. pair going right and up starts at [4, 2], with sum 31 and components 15 and 16 
0

這是一種使用簡單(但很長)的代碼來完成它的方法。

既然你正在尋找連續數最大的一對,你應該首先創建一個函數,它需要一個單元格並且找到它所有的連續和。

consec <- function(ma,y,x){ 
    return(
    c(if(x<ncol(ma))    ma[y,x] + ma[y,x+1], 
     if(x>1)      ma[y,x] + ma[y,x-1], 
     if(y<nrow(ma))    ma[y,x] + ma[y+1,x], 
     if(y>1)      ma[y,x] + ma[y-1,x], 
     if(x<ncol(ma) & y<nrow(ma)) ma[y,x] + ma[y+1,x+1], 
     if(x>1 & y<nrow(ma))  ma[y,x] + ma[y+1,x-1], 
     if(x<ncol(ma) & y>1)  ma[y,x] + ma[y-1,x+1], 
     if(x>1 & y>1)    ma[y,x] + ma[y-1,x-1]) 
) 
} 

此功能(if語句)確保我們不要去出界,因爲在邊境細胞將有小於8樓的鄰居,形成對連續帶的左半邊。然後右半部分獲得連續對的總和並將其添加到列表中。

現在,如果您使用consec(ma, 3, 2),它會爲您提供ma[3,2]的連續總和向量。

接下來,我們要填充每個單元格的最高連續總和的第二個矩陣。您可以使用以下代碼創建具有正確尺寸的空白矩陣。

ma2 <- matrix(0, nrow = nrow(ma), ncol = ncol(ma)) 

現在用循環和前面創建的consec函數填充它。

for(i in 1:nrow(ma)){ 
    for(j in 1:ncol(ma)){ 
    ma2[i,j] <- max(consec(ma,i,j)) 
    } 
} 

現在,我們有我們連續總和的矩陣,我們可以找到它的最大金額,以及它的座標將對應的地方,我們要在原有的矩陣看。

ma.max <- which(ma2 == max(ma2), arr.ind = TRUE) 

現在,如果僅存在一個對數字它是最大值,那麼ma.max將有兩條線(在同一對的兩個置換)。您可以使用:

ma[ma.max[1,1], ma.max[1,2]]; ma[ma.max[2,1], ma.max[2,2]] 

要顯示它們。在這種情況下,我們得到1516,所以它的工作。

如果您有更多的最大值,那麼在上面的代碼中增加數字以獲得下一對(3和4),依此類推。你甚至可以調整consec函數,例如,如果你不想要對角線連續,然後刪除列表的最後四行。