wen
wen

Reputation: 1935

How to effectively sort the rows of a matrix given any number of columns?

Let's create a fake test of three items only (n=3). One can answer each item either right (1) or wrong (0). There are only eight possibilities of the test results, i.e. all 1s, all 0s, and some combinations in between. The following code can be used to simulation this scenario:

n=3; m=0
while(m!=2^n) {
 tmat = t(sapply(1:(10*2^n), function(x) sample(c(0,1), n, replace=T)))
 pats = apply(tmat, 1, paste, collapse="/")
 pats = unique(pats)
 m = length(pats)
}
xmat = matrix(as.numeric(unlist(strsplit(pats, "/"))), ncol=n, nrow=m, byrow=T)

However, now I need to sort the rows of xmat and the results should look like this:

     [,1] [,2] [,3] [,4]
[1,]    0    0    0    0
[2,]    1    0    0    1
[3,]    0    1    0    1
[4,]    0    0    1    1
[5,]    1    1    0    2
[6,]    1    0    1    2
[7,]    0    1    1    2
[8,]    1    1    1    3

I used this code to get the above results:

# create the fourth column which is the total score
xmat = cbind(xmat, rowSums(xmat)) 

# order by the 4th column, then 3rd column, then 2nd column.
xmat = xmat[order(xmat[,4], xmat[,3], xmat[,2]),] 

My problem is that I will have any number of columns n in the future (n = 3 in this case). I cannot manually put n-1 terms in the code to order the matrix like this:

xmat = xmat[order(xmat[,n+1], xmat[,n], xmat[,n-1]), ... , xmat[,2])

Is there a easy way to do the last step?

Thank you in advance!

Upvotes: 0

Views: 102

Answers (1)

flodel
flodel

Reputation: 89057

I think this should do it:

xmat[do.call(order, rev(split(xmat, col(xmat)))), ]

where:

  1. split(xmat, col(xmat) splits your matrix into a list of its columns
  2. rev reorders the list (last column first)
  3. do.call calls order on the list

Upvotes: 4

Related Questions