Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I would like to sort a matrix in descending order first by the total of each column, then by the total of each row, but without changing their content. For example, if I had:

TableForm[{{0, 0, 1, 1}, {0, 0, 0, 1}, {1, 0, 1, 1}, {1, 1, 1, 1}}, 
 TableHeadings -> {Range[1, 4], Range[1, 4]}]

I want to sort first the columns:

TableForm[{{1, 1, 0, 0}, {1, 0, 0, 0}, {1, 1, 1, 0}, {1, 1, 1, 1}}, 
 TableHeadings -> {Range[1, 4], {"4", "3", "1", "2"}}]

Then the rows:

TableForm[{{1, 1, 1, 1}, {1, 1, 1, 0}, {1, 1, 0, 0}, {1, 0, 0, 0}}, 
 TableHeadings -> {{"4", "3", "1", "2"}, {"4", "3", "1", "2"}}]

The goal is to get as many 1's as possible to the upper-left corner. I added TableHeadings to this mockup of the desired result simply to show the content of the columns/rows remains the same. If there is a better way other than using the Total for each column/row that is fine too. Any help is much appreciated!

share|improve this question
add comment

2 Answers

up vote 3 down vote accepted

Ordering and Part are applicable to this kind of problem. Reverse is needed below as you want to place larger elements to the upper left rather than lower right.

tab = {{0, 0, 1, 1}, {0, 0, 0, 1}, {1, 0, 1, 1}, {1, 1, 1, 1}};

tab = tab[[All, Reverse @ Ordering[tab ~Total~ {1}]]];

tab[[Reverse @ Ordering[tab ~Total~ {2}]]] // TableForm

Mathematica graphics

(This may not be the most efficient algorithm to achieve your goal.)


I believe this can also be done with one application of Part by computing the Ordering for each level beforehand:

newSort[x_?ArrayQ] :=
  x[[##]] & @@ (Reverse@Ordering[x ~Total~ {#}] & /@ {2, 1})

newSort[tab]

This could be easily extended to greater dimensions by replacing {2, 1} with Range[ArrayDepth@x, 1, -1].

share|improve this answer
    
I knew about Part, but Ordering was new for me. Thanks @Mr.Wizard! –  Pancholp Dec 4 '12 at 12:45
    
@Pancholp You're welcome. Please see the update I just made. –  Mr.Wizard Dec 4 '12 at 13:05
add comment

Using Sort :

Sort[Transpose[Sort[Transpose[tab], Total[#1] > Total[#2] &]], Total[#1] > Total[#2] &]
share|improve this answer
    
Thanks @b.gatessucks! This one works well too. –  Pancholp Dec 4 '12 at 12:44
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.