5
$\begingroup$

I have a matrix with ten columns, and I want to rearrange these columns with three conditions.

  1. Column 1+2n and 2+2n (0<=n=<4) always remain together and in the same order (1+2n before 2+2n). Now we can say that we have five sets of columns, each having two columns.

  2. The 2+2n th columns should be sorted with respect to the first elements in them.

  3. In case first elements of any two 2+2n columns are same, they should be arranged with respect to the first elements of the corresponding 1+2n columns.

For example if the simplified matrix has only one row {1, 4, 7, 5, 8, 5, 0, 2, 3, 9}, it should be rearranged to {0, 2, 1, 4, 7, 5, 8, 5, 3, 9}.

Thanks for the help!

$\endgroup$
2
  • $\begingroup$ Would you say this result looks correct? $\endgroup$
    – Syed
    Commented Oct 13, 2021 at 17:20
  • $\begingroup$ Yes. It is what I want. $\endgroup$
    – user49535
    Commented Oct 13, 2021 at 17:28

1 Answer 1

4
$\begingroup$

Update: A generalization that takes partition sizes, reference row and column sort order for sorting:

ClearAll[partitionedOrderingBy]
partitionedOrderingBy[m_, referenceRow_: 1, partitionSize_: 2, sortOrder_: Automatic] :=
 Module[{
  partitionedIndices = Partition[Range@Dimensions[m][[2]], partitionSize],
   sortFunctions = Table[With[{i = i}, m[[referenceRow, #[[i]]]] &], 
     {i, sortOrder /. Automatic -> Reverse @ Range @ partitionSize}]},
  Flatten @ SortBy[sortFunctions] @ partitionedIndices]

Examples:

SeedRandom[1]
mat = RandomInteger[10, {3, 12}];

MatrixForm @ mat

enter image description here

mat[[All, partitionedOrderingBy[mat]]]

enter image description here

highlightPartitions[m_, partitionSize_: 2] := MapIndexed[
 Highlighted[Style[#, 16], Background->ColorData[97]@(Ceiling[#2[[2]]/partitionSize])]&,
 m, {2}]

MatrixForm[#, TableHeadings -> {{1, 2, 3}, Range@12}] & @ highlightPartitions[mat]

enter image description here

Sort using default values for arguments:

With[{r = 1}, 
 MatrixForm[highlightPartitions[mat, 2][[All, #]], 
    TableHeadings -> {Range[3] /. r -> Style[r, 20, Bold, Red], #}] &@
  partitionedOrderingBy[mat]]

enter image description here

Use the second row as reference row for sorting:

With[{r = 2}, 
 MatrixForm[highlightPartitions[mat, 2][[All, #]], 
    TableHeadings -> {Range[3] /. r -> Style[r, 20, Bold, Red], #}] &@
  partitionedOrderingBy[mat, r]]

enter image description here

Use the lexical order {1,2} instead of the default {2,1}:

With[{r = 1}, 
 MatrixForm[highlightPartitions[mat, 2][[All, #]], 
    TableHeadings -> {Range[3] /. r -> Style[r, 20, Bold, Red], #}] &@
  partitionedOrderingBy[mat, r, 2, {1, 2}]]

enter image description here

Partition columns into consecutive triples (instead of consecutive pairs):

MatrixForm[#, TableHeadings -> {{1, 2, 3}, Range@12}] & @ highlightPartitions[mat, 3]

enter image description here

Use the default reference row (1) for sorting:

With[{r = 1}, 
 MatrixForm[highlightPartitions[mat, 3][[All, #]], 
    TableHeadings -> {Range[3] /. r -> Style[r, 20, Bold, Red], #}] &@
  partitionedOrderingBy[mat, r, 3]]

enter image description here

Use row 3 as the reference row:

With[{r = 3}, 
 MatrixForm[highlightPartitions[mat, 3][[All, #]], 
    TableHeadings -> {Range[3] /. r -> Style[r, 20, Bold, Red], #}] &@
  partitionedOrderingBy[mat, r, 3]]

MatrixForm @ highlightPartitions[mat, 3][[All, partitionedOrderingBy[mat, 2, 3]]]

enter image description here

Use partition size 4 and first row as reference row:

MatrixForm[#, TableHeadings -> {{1, 2, 3}, Range@12}] &@ highlightPartitions[mat, 4]

enter image description here

With[{r = 1}, 
 MatrixForm[highlightPartitions[mat, 4][[All, #]], 
    TableHeadings -> {Range[3] /. r -> Style[r, 20, Bold, Red], #}] &@
  partitionedOrderingBy[mat, r, 4]]

enter image description here

Original answer:

For input matrix m, Partition the column indices and lexically sort the pairs of indices based on first row elements of m )so that the index pair {pi1, pi2} comes before the pair {pj1, pj2} iff m[[1,pi2]] < m[[1,pj2]] or m[[1,pi2]] == m[[1,pj2]] and m[[1,pi1]] < m[[1,pj1]]):

ClearAll[partitionAndSort]

partitionAndSort[m_] := Module[{
   partitionedColumnIndices = Partition[Range @ Dimensions[m][[2]], 2], 
   lexicalSortFunctions = {m[[1, #[[2]]]] &, m[[1, #[[1]]]] &},
   columnsOrdering},
  columnsOrdering =  Flatten @ SortBy[lexicalSortFunctions] @ partitionedColumnIndices;
  m[[All, columnsOrdering]]]

Example:

SeedRandom[1]
mat = RandomInteger[10, {3, 10}];

MatrixForm @ mat

enter image description here

MatrixForm @ partitionAndSort @ mat 

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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