# Permuting the rows of a matrix based on given a given permutation

Suppose I am given an mXn matrix A, and I have a permutation of {1,…,m}, for example by

``````p = sortperm(A[:,1]);
``````

I now wish to rearrange the wors of `A` based on `p`. How do I do that ? The `permute!()` function only applies to vectors, as shown here. I can always loop over the columns, as in

``````for j in 1:size(A,2)
permute!(A[:,j], p);
end
``````

but is there a better way ?

1 Like

Note that this permutes a copy of the column, unless you switch to using views (e.g. wrapping the code block or the line in a `@views` macro call).

For an alternative approach, you could write something similar to the `Base.permutecols!!` function (which permutes columns, not rows). (Since Julia’s `Array` is column-major, however, permuting rows with this algorithm will probably not be as efficient as permuting columns.) Or your could rearrange your code to swap dimensions on your array, and then call the `Base.permutecols!!` function directly. (It has a double `!!` because it also overwrites the permutation array `p`.)

3 Likes

Is this a (new) convention? Is it meant to signify that more than one passed argument is being mutated, or is its meaning more specific?

A couple of Base functions use it to indicate that multiple arguments are mutated, but I don’t think it’s a very widespread convention in Julia.

2 Likes

You can use `sortslices`, it sorts by rows, columns, or any row/column specified by the user.

``````julia> A = rand(0:9,5,5)
5×5 Array{Int64,2}:
4  6  4  6  3
2  7  5  5  2
7  7  0  4  3
4  5  2  5  6
6  5  8  1  0

julia> sortslices(A, dims=1)
5×5 Array{Int64,2}:
2  7  5  5  2
4  5  2  5  6
4  6  4  6  3
6  5  8  1  0
7  7  0  4  3
``````
1 Like

Thank you. Although I was looking for an in-place algorithm, this function is a very useful to learn. From the examples that you provided, it seems that the sorting is only according to the first column or row. But what if I try to rearrange the rows in in increasing order of the second column ? You said that it can be done, could you give me the code to do it ? Julia’s documentation on sortclices does not provide a solution.

Thank you, however the function permutecolums itself did not work.

``````julia> permutecols!!(A,p)
ERROR: UndefVarError: permutecols!! not defined
Stacktrace:
[1] top-level scope at none:0
``````

In fact, it seems that Base does not have any such function defined.

``````julia> Base.permute
permute!     permute!!     permutedims   permutedims!
``````

In the hyperlink that you provided, the function was defined in the Combinatorics.jl package. importing the package also did not work. I tried copying the function definition and explicitly defining `permutecolumns!!`. But this gives the error

``````julia> permutecols!!(A,p)
ERROR: UndefVarError: require_one_based_indexing not defined
Stacktrace:
[1] permutecols!!(::Array{Float64,2}, ::Array{Int64,1}) at .\REPL[22]:2
[2] top-level scope at none:0
``````

Yes, as I said you can sort by any row/column you want which can be very useful. Just override the `lt` function to specify how the new comparison is done. Searching for documentation inside the REPL is so easy, just type `?sortslices` and you get good examples.

``````julia> A = rand(0:9,5,5)
5×5 Array{Int64,2}:
6  5  5  0  0
3  4  5  9  5
0  2  5  0  5
9  9  1  7  2
3  1  2  4  7

julia> sortslices(A, dims=1, lt=(x,y)->isless(x[2],y[2]))
5×5 Array{Int64,2}:
3  1  2  4  7
0  2  5  0  5
3  4  5  9  5
6  5  5  0  0
9  9  1  7  2
``````
1 Like

Thanks. I did search for sortslices. But there is no way anyone can possibly understand from the documentation alone that `lt=(x,y)->isless(x[2],y[2]))` is supposed to mean ``by second column".

It was added in Julia 1.2.

1 Like

You can also write `sortslices(A, dims=1, by=row->row[2])`, although I agree it’s not super-obvious what’s going to happen.

2 Likes

I see

I think this code doesn’t work b/c you haven’t specified `j`