# Swap cols/rows of a matrix

**URL:** <https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904>\
**Category:** General Usage\
**Tags:** matrix\
**Created:** [October 6, 2020, 11:33pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904 "2020-10-06T23:33:29Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![hytonwons](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hytonwons/32/8787_2.png) [@hytonwons](https://discourse.julialang.org/u/hytonwons)\
**Post date:** [October 6, 2020, 11:33pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/1 "2020-10-06T23:33:29Z")

</div>

Hi,

I need to swap columns or rows of a matrix. I have two ideas:  
(1). Create a new matrix and copy cols/rows to the new matrix. We may use @view.  
(2). Multiply by a permutation matrix. Of course, we also need to create that permutation matrix (but it’s sparse)

To my understanding, multiplication takes O(n^3) given a square matrix, but not sure how multiplying with a sparse matrix will make a difference or not.  
I’m wondering which way is more preferable in terms of performance?

Your help is appreciated in advance!

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [October 6, 2020, 11:49pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/2 "2020-10-06T23:49:08Z")

</div>

I think it depends also on what you have to do with yr matrix later… With @view you have no allocations but you also have a structure where the data is no longer contigue, so if you have to use it “often” is penalising…

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 7, 2020, 12:48am UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/4 "2020-10-07T00:48:32Z")

</div>

I am not sure if I understand what you want, but for swapping cols, for example, I would do this, which does not allocate anything:

```julia
julia> function swapcol!(x,i,j)
         for k in axes(x,1) # edited according to next answer
           idata = x[k,i]
           x[k,i] = x[k,j]
           x[k,j] = idata
         end
       end
swapcol! (generic function with 1 method)

julia> x = [1 2 3 ; 4 5 6]
2×3 Array{Int64,2}:
 1 2 3
 4 5 6

julia> swapcol!(x,1,2)

julia> x
2×3 Array{Int64,2}:
 2 1 3
 5 4 6

julia> @btime swapcol!($x,1,2)
  4.634 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![hytonwons](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hytonwons/32/8787_2.png) [@hytonwons](https://discourse.julialang.org/u/hytonwons)\
**Post date:** [October 7, 2020, 6:25am UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/5 "2020-10-07T06:25:14Z")

</div>

agreed, thanks!

---

<div class="post-metadata">

**Author:** ![hytonwons](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hytonwons/32/8787_2.png) [@hytonwons](https://discourse.julialang.org/u/hytonwons)\
**Post date:** [October 7, 2020, 6:28am UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/6 "2020-10-07T06:28:42Z")

</div>

Interesting. Why don’t we need to allocate memory for this local temp variable "idate’'?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 7, 2020, 7:05am UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/7 "2020-10-07T07:05:19Z")

</div>

> [@lmiq](#):
>
> ```julia
> julia> function swapcol!(x,i,j)
> for k in axes(x)[1]
> idata = x[k,i]
> x[k,i] = x[k,j]
> x[k,j] = idata
> end
> end
> 
> ```

You don’t need the temporary variable:

```julia
function _swapcol!(x,i,j)
    for k in axes(x, 1) # <- give dimension as input to axes function
        x[k, i], x[k, j] = x[k, j], x[k, i]
    end
end

```

If you are reshuffling the columns (or rows) you can supply a vector of indices:

```julia
julia> x = collect(reshape(1:12, 3, 4))
3×4 Array{Int64,2}:
 1 4 7 10
 2 5 8 11
 3 6 9 12

julia> x[:, [2,3,1,4]]
3×4 Array{Int64,2}:
 4 7 1 10
 5 8 2 11
 6 9 3 12

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 7, 2020, 7:13am UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/8 "2020-10-07T07:13:11Z")

</div>

> [@hytonwons](#):
>
> Why don’t we need to allocate memory for this local temp variable "idate’’?

`idata` is just a scalar value, so doesn’t need any memory allocation, unlike an array. But as I said, you don’t really need to create that variable explicitly (though, of course, `x, y = y, x` will do that ‘under the hood’.)

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 7, 2020, 9:01am UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/9 "2020-10-07T09:01:31Z")

</div>

> [@hytonwons](#):
>
> Interesting. Why don’t we need to allocate memory for this local temp variable "idate’’?

This is a good question which I do not completely understand. Because the scope of that scalar is only local to the loop, I guess it is only created in a local memory during computation that does not count as an allocation. I do not know the details of that.

As DNF pointed out, in his version in which this scalar is not created explicitly, it is created anyway. Effectively the `@code_typed` of the two versions are identical and, if I understand what is there (not sure, though), this part shows that `%16` creates a copy of element `i`, which is then used in the third line of instruction `%17`.

```julia
│ %16 = Base.arrayref(false, x, %14, i)::Int64
│ %17 = Base.arrayref(false, x, %14, j)::Int64
│ Base.arrayset(false, x, %17, %14, i)::Array{Int64,2}
│ Base.arrayset(false, x, %16, %14, j)::Array{Int64,2}

```

ps: I think that the counter of the loop must be created in a similar way and does not count as an allocation either.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [January 4, 2024, 4:22pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/10 "2024-01-04T16:22:26Z")

</div>

Sorry for reviving this old thread, but is there something builtin for this now?

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [January 4, 2024, 4:45pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/11 "2024-01-04T16:45:34Z")

</div>

There’s nothing magic about built-in functions. The [suggestions provided above](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/7) above are just a couple of lines and are basically as good as anything.

There is the internal and undocumented `LinearAlgebra.rcswap!` that swaps a pair of rows _and_ columns. But I would discourage using that because it is internal (it could change or be removed at any time). Also, it doesn’t perform the originally-requested task of swapping only rows or only columns.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 4, 2024, 7:01pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/12 "2024-01-04T19:01:15Z")

</div>

> [@mikmoore](#):
>
> There is the internal and undocumented `LinearAlgebra.rcswap!` that swaps a pair of rows _and_ columns. But I would discourage using that because it is internal (it could change or be removed at any time). Also, it doesn’t perform the originally-requested task of swapping only rows or only columns.

There is also [`Base.swapcols!`](https://github.com/JuliaLang/julia/blob/5a28cf5ec3863a2f5825a8c4b9aa035791c60ace/base/combinatorics.jl#L96C1-L105), but again this is an internal function that may disappear in the future. But since it is only a 10-line function that doesn’t depend on any other `Base` internals it is perfectly reasonable to copy-and-paste it into your code as needed:

```julia
# swap columns i and j of a, in-place
function swapcols!(a::AbstractMatrix, i, j)
    i == j && return
    cols = axes(a,2)
    @boundscheck i in cols || throw(BoundsError(a, (:,i)))
    @boundscheck j in cols || throw(BoundsError(a, (:,j)))
    for k in axes(a,1)
        @inbounds a[k,i],a[k,j] = a[k,j],a[k,i]
    end
end

```

It’s very similar to the suggestions above, except it adds an `@inbounds` annotation and consequently requires bounds checks before the loop. You could also do e.g.

```julia
if isdefined(Base, :swapcols!)
    using Base: swapcols! # assumes the API hasn't changed
else
    function swapcols!(...)
        ...
    end
end

```

Inspecting `Base` code can be a useful exercise, even if you end up copy-pasting it for safety, since it usually has been reviewed by multiple people and tries extra hard to be robust and reasonably efficient.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [January 4, 2024, 7:09pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/13 "2024-01-04T19:09:36Z")

</div>

```julia
swap!(m,c1,c2)= begin m[:,c1],m[:,c2]= m[:,c2],m[:,c1];nothing end

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 4, 2024, 7:28pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/14 "2024-01-04T19:28:32Z")

</div>

This allocates two temporary vectors, though.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 4, 2024, 7:35pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/15 "2024-01-04T19:35:10Z")

</div>

Just for fun:

```julia
swap2cols(M,i,j) = M[:, replace(axes(M,2), i=>j, j=>i)]

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 4, 2024, 8:51pm UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/16 "2024-01-04T20:51:38Z")

</div>

Same idea, but for swapping in place (not tested):

```julia
swap2cols!(M,i,j) = Base.permutecols!!(M, replace(axes(M,2), i=>j, j=>i))

```

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [January 5, 2024, 8:57am UTC](https://discourse.julialang.org/t/swap-cols-rows-of-a-matrix/47904/17 "2024-01-05T08:57:03Z")

</div>

Thanks, this is what I do generally, it’s just one of those cases where it feels a bit clunky to have some unrelated `utils.jl` file in my package to have this sort of simple-but-unrelated-to-the-actual package functionality.

Maybe a bit like the discussion on whether `mean` should be available when people could just write `sum(x)/length(x)` - I get these are all language design decisions which can be reasoned about endlessly and I don’t intend to do that here, just wanted to check in.
