Albert
Albert

Reputation: 197

Getting a matrix ordered

I would like to order and trasform the values of a matrix from the biggest to the smallest value as in this simple and replicable example :

 #From :
 d<- c(-2,-34,25,0,13,0,25,-2,1)
 m<- matrix(d,3,3)
 m
     [,1] [,2] [,3]
[1,]   -2    0   25
[2,]  -34   13   -2
[3,]   25    0    1

# To:
m1
     [,1] [,2] [,3]
[1,]    5    4    1
[2,]    6    2    5
[3,]    1    4    3

#25: biggest number therefore -->(1)
#13: second biggest one ---> (2)
# ecc ...
#-34: the smallest one ---> (6)

Any help? Thanks

Upvotes: 5

Views: 138

Answers (3)

MichaelChirico
MichaelChirico

Reputation: 34703

An approach with base rank:

#get unique values, since rank itself doesn't
#  seem to have an option that allows the 
#  ranking system you have in mind
u_m = unique(c(m))

#"merge" with match
matrix(rank(-u_m)[match(m, u_m)], nrow = 3L, ncol = 3L)
#      [,1] [,2] [,3]
# [1,]    5    4    1
# [2,]    6    2    5
# [3,]    1    4    3

While base::rank doesn't have a way to get what you want right away, we can use frank (as noted by @eddi), an improved and efficient version of rank in the data.table package, like so:

library(data.table)
matrix(frank(-m, ties.method = "dense"), nrow = 3L, ncol = 3L)

Or, if the matrix part looks ugly, just pre-allocate something as a matrix, a la

m1 = m
m1[] = frank(-m, ties.method = "dense")

Upvotes: 6

lebatsnok
lebatsnok

Reputation: 6459

You can convert d to factor and then get rid of the levels. (This means you don't need any extra packages.)

m1 <- m
m1[]<-unclass(factor(d, levels = sort(unique(d), decreasing=TRUE)))
# alternative solutions from comments
# or levels=sort(-d), thanks, akrun
# or, to make it shorter: m1[] <- unclass(factor(-d))
# or, [eddi's suggestion using implicit conversions]: m1[] <- factor(-m) 
m1
#      [,1] [,2] [,3]
# [1,]    5    4    1
# [2,]    6    2    5
# [3,]    1    4    3

Upvotes: 10

akrun
akrun

Reputation: 887048

We can use dense_rank

library(dplyr)
m1 <- m
m1[] <- dense_rank(-m)
m1
#    [,1] [,2] [,3]
#[1,]    5    4    1
#[2,]    6    2    5
#[3,]    1    4    3

Upvotes: 2

Related Questions