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
mat[[All, partitionedOrderingBy[mat]]]
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]
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]]
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]]
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}]]
Partition columns into consecutive triples (instead of consecutive pairs):
MatrixForm[#, TableHeadings -> {{1, 2, 3}, Range@12}] & @ highlightPartitions[mat, 3]
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]]
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]]]
Use partition size 4
and first row as reference row:
MatrixForm[#, TableHeadings -> {{1, 2, 3}, Range@12}] &@ highlightPartitions[mat, 4]
With[{r = 1},
MatrixForm[highlightPartitions[mat, 4][[All, #]],
TableHeadings -> {Range[3] /. r -> Style[r, 20, Bold, Red], #}] &@
partitionedOrderingBy[mat, r, 4]]
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
MatrixForm @ partitionAndSort @ mat