Reputation: 797
I have a symmetric matrix mat
:
A B C
A 1 . .
B . 1 .
C . . 1
And I want to calculate the two highest elements of it. Now since it's a symmetric matrix I thought of using upper.tri
like so:
mat.tri<-upper.tri(mat) # convert to upper tri
mat.ord<-order(mat.tri,na.last=TRUE,decreasing=TRUE)[1:2] # order by largest
a.ind<-which(mat%in%mat.tri[mat.ord]) # get absolute indices
r.ind<-arrayInd(a.ind,dim(mat)) # get relative indices
# get row/colnames using these indices
So the above is such a roundabout way of doing things, and even then the output has 'duplicate' rows in that they are just transposed..
Anyone got a more intuitive way of doing this?
Thanks.
Upvotes: 1
Views: 147
Reputation: 179468
Liberally borrowing from the excellent ideas of @SimonO'Hanlon
and @lukeA
, you can construct a two-liner function to do what you want. I use:
arrayInd()
to return the array indexorder()
to order the upper triangular elementsNA
, using m[lower.tr(m)] <- NA
Try this:
whichArrayMax <- function(m, n=2){
m[lower.tri(m)] <- NA
arrayInd(order(m, decreasing=TRUE)[seq(n)], .dim=dim(m))
}
mat <- matrix( c(1,2,3,2,1,5,3,5,1) , 3 , byrow = TRUE )
mat
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 1 5
[3,] 3 5 1
whichArrayMax(mat, 2)
[,1] [,2]
[1,] 2 3
[2,] 1 3
Upvotes: 1
Reputation: 54247
arrayInd(which.max(mat), .dim=dim(mat))
which is basically the same as which( mat == max(mat) , arr.ind = TRUE )[1,]
from @SimonO'Hanlon, but more efficient.
Upvotes: 0