# Sorting matrix according to the first column

**URL:** <https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196>\
**Category:** General Usage\
**Tags:** sorting, matrix\
**Created:** [March 27, 2024, 7:05pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196 "2024-03-27T19:05:28Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![baprata](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baprata/32/204269_2.png) [@baprata](https://discourse.julialang.org/u/baprata)\
**Post date:** [March 27, 2024, 7:05pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/1 "2024-03-27T19:05:28Z")

</div>

In the matrix below, the first, second, and third columns represent the height, area, and volume of rectangular objects, respectively. I need to sort the items in non-ascending order of height (from the highest to the lowest). After sorting, the associated area and volume for each item should remain correctly aligned with its height.

4.27 122.62 102.83  
2.18 178.34 214.79  
29.58 273.83 840.17  
18.99 89.68 683.06  
10.77 269.75 1928.60

For example, considering this matrix, I need the following matrix sorted:

29.58 273.83 840.17  
18.99 89.68 683.06  
10.77 269.75 1928.60  
4.27 122.62 102.83  
2.18 178.34 214.79

How should I proceed?

---

<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:** [March 27, 2024, 7:11pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/2 "2024-03-27T19:11:09Z")

</div>

Try:

```julia
julia> sortslices(A, dims=1, rev=true)
5×3 Matrix{Float64}:
 29.58 273.83 840.17
 18.99 89.68 683.06
 10.77 269.75 1928.6
  4.27 122.62 102.83
  2.18 178.34 214.79

```

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 27, 2024, 8:18pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/3 "2024-03-27T20:18:20Z")

</div>

Another option:

```julia
julia> @view A[sortperm(A[:,1]; rev=true),:]
5×3 view(::Matrix{Float64}, [1, 2, 3, 4, 5], :) with eltype Float64:
 29.58 273.83 840.17
 18.99 89.68 683.06
 10.77 269.75 1928.6
  4.27 122.62 102.83
  2.18 178.34 214.79

```

This doesn’t materialize the sorted matrix which may be more efficient for the correct use case.

---

<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:** [March 27, 2024, 8:43pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/4 "2024-03-27T20:43:08Z")

</div>

for this small matrix the first expression seems more efficient (but perhaps for larger matrices the others work better)

```julia
julia> using BenchmarkTools

julia> @btime stack(sort(eachrow(A),by=first, rev=true),dims=1)
  375.879 ns (3 allocations: 464 bytes)
5×3 Matrix{Float64}:
 29.58 273.83 840.17
 18.99 89.68 683.06
 10.77 269.75 1928.6
  4.27 122.62 102.83
  2.18 178.34 214.79

julia> @btime sortslices(A, dims=1, rev=true)
  926.667 ns (12 allocations: 1008 bytes)
5×3 Matrix{Float64}:
 29.58 273.83 840.17
 18.99 89.68 683.06
 10.77 269.75 1928.6
  4.27 122.62 102.83
  2.18 178.34 214.79

julia> @btime @view A[sortperm(A[:,1]; rev=true),:]
  576.023 ns (5 allocations: 272 bytes)
5×3 view(::Matrix{Float64}, [3, 4, 5, 1, 2], :) with eltype Float64:
 29.58 273.83 840.17
 18.99 89.68 683.06
 10.77 269.75 1928.6
  4.27 122.62 102.83
  2.18 178.34 214.79

```

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 27, 2024, 10:11pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/5 "2024-03-27T22:11:19Z")

</div>

> [@rocco\_sprmnt21](#):
>
> `@view A[sortperm(A[:,1]; rev=true),:]`

Oooh, I forgot another `@view`:

```julia
@view A[sortperm(@view A[:,1]; rev=true),:]

```

(maybe this is better)

---

<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:** [March 27, 2024, 10:13pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/6 "2024-03-27T22:13:02Z")

</div>

> [@Dan](#):
>
> `@view A[sortperm(@view A[:,1]; rev=true),:]`

Cleaner to use `@views A[sortperm(A[:,1]; rev=true),:]`

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [March 27, 2024, 11:19pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/7 "2024-03-27T23:19:51Z")

</div>

@Dan when you state that this does not materialize, could you explain it a bit more?

Does this mean that instead of sorting an array/matrix/whatever, one can get a `view` of the element in a sorted order?

And if I update elements of this view, then it should propagate correctly to the initial element?

Kind regards

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 27, 2024, 11:51pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/8 "2024-03-27T23:51:14Z")

</div>

Seems you got it right:

> [@Ahmed\_Salih](#):
>
> Does this mean that instead of sorting an array/matrix/whatever, one can get a `view` of the element in a sorted order?

Yes

> [@Ahmed\_Salih](#):
>
> And if I update elements of this view, then it should propagate correctly to the initial element?

Yes

“does not materialize” means does not have to allocate memory and set it to these values, but the required values are calculated on the CPU from the inputs as needed. Basically, this is the advantage of views, which just tell the CPU where to find the original array and how to calculate a modified index into the original array.

BTW, on my machine, adding the missing `@view`, using stevengj’s style, benchmarks more than 5x the benchmark without the second `@view`:

```julia
julia> @btime @view $A[sortperm($A[:,1]; rev=true),:]
  230.680 ns (2 allocations: 192 bytes)
5×3 view(::Matrix{Float64}, [1, 2, 3, 4, 5], :) with eltype Float64:
 29.58 273.83 840.17
:
julia> @btime @views $A[sortperm($A[:,1]; rev=true),:]
  33.598 ns (1 allocation: 96 bytes)
5×3 view(::Matrix{Float64}, [1, 2, 3, 4, 5], :) with eltype Float64:
 29.58 273.83 840.17
:

```

33 ns vs. 230 ns

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [March 28, 2024, 6:36am UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/9 "2024-03-28T06:36:39Z")

</div>

> [@Dan](#):
>
> “does not materialize” means does not have to allocate memory and set it to these values, but the required values are calculated on the CPU from the inputs as needed.

Just note that this is not free. Each array access now requires an additional load. If you plan to access the sorted array a great number of times, then this additional cost might add up and you could come out slower.

```julia-repl
julia> using BenchmarkTools; v = rand(1000); inds = rand(1:1000, 10000);
julia> @btime let s = 0, v = view($v, sortperm($v))
        for i in $inds
            s+= v[i]
        end
        s
    end

  72.009 μs (2 allocations: 15.88 KiB)
4971.880280956974

julia> @btime let s = 0, v = sort($v)
        for i in $inds
            s+= v[i]
        end
        s
    end

  58.389 μs (3 allocations: 18.06 KiB)
4971.880280956974

```

Interestingly enough if I directly interpolate the array/view then there is no runtime difference:

```julia-repl
julia> @btime let s = 0
       for i in $inds
           s+= $(sort(v))[i]
       end
       s
       end
  39.392 μs (0 allocations: 0 bytes)
4971.880280956974

julia> @btime let s = 0
       for i in $inds
           s+= $(view(v,sortperm(v)))[i]
       end
       s
       end

  39.462 μs (0 allocations: 0 bytes)
4971.880280956974

```

---

<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:** [March 28, 2024, 7:36am UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/10 "2024-03-28T07:36:26Z")

</div>

Linking [similar thread](https://discourse.julialang.org/t/sort-matrix-based-on-the-elements-of-a-specific-column/23475).

---

<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:** [March 28, 2024, 7:58am UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/11 "2024-03-28T07:58:54Z")

</div>

in fact it seemed strange that it could be an “original” topic 😁

I tried various combinations of the parameters of the various expressions.  
This seems to be the most efficient

```julia
@btime @views $A[sortperm($A[:,1]; lt=(x,y)->y<x),:]

```

---

<div class="post-metadata">

**Author:** ![baprata](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baprata/32/204269_2.png) [@baprata](https://discourse.julialang.org/u/baprata)\
**Post date:** [March 28, 2024, 10:51am UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/12 "2024-03-28T10:51:02Z")

</div>

Dear colleagues, thank you very much for your support. Bruno

---

<div class="post-metadata">

**Author:** ![zdenek\_hurak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zdenek_hurak/32/53118_2.png) [@zdenek\_hurak](https://discourse.julialang.org/u/zdenek_hurak)\
**Post date:** [March 28, 2024, 12:43pm UTC](https://discourse.julialang.org/t/sorting-matrix-according-to-the-first-column/112196/13 "2024-03-28T12:43:49Z")

</div>

If what is really needed is the operation on matrices, others have already provided their solutions. But I can’t resist to point out that if your matrix represents data with this column interpretation, you may want to consider using some higher-level data type for your data. Namely, `DataFrame` from [DataFrames.jl](https://dataframes.juliadata.org/stable/) package. Have a look how convenient and systematic this sorting of your _table_ is:

```julia
julia> using DataFrames

julia> data = [4.27 122.62 102.83;
               2.18 178.34 214.79;
               29.58 273.83 840.17;
               18.99 89.68 683.06;
               10.77 269.75 1928.60]
5×3 Matrix{Float64}:
  4.27 122.62 102.83
  2.18 178.34 214.79
 29.58 273.83 840.17
 18.99 89.68 683.06
 10.77 269.75 1928.6

julia> df = DataFrame(height = data[:, 1], area = data[:, 2], volume = data[:, 3])
5×3 DataFrame
 Row │ height area volume  
     │ Float64 Float64 Float64 
─────┼───────────────────────────
   1 │ 4.27 122.62 102.83
   2 │ 2.18 178.34 214.79
   3 │ 29.58 273.83 840.17
   4 │ 18.99 89.68 683.06
   5 │ 10.77 269.75 1928.6

julia> println(df)
5×3 DataFrame
 Row │ height area volume  
     │ Float64 Float64 Float64 
─────┼───────────────────────────
   1 │ 4.27 122.62 102.83
   2 │ 2.18 178.34 214.79
   3 │ 29.58 273.83 840.17
   4 │ 18.99 89.68 683.06
   5 │ 10.77 269.75 1928.6

julia> sort!(df, :height, rev=true)
5×3 DataFrame
 Row │ height area volume  
     │ Float64 Float64 Float64 
─────┼───────────────────────────
   1 │ 29.58 273.83 840.17
   2 │ 18.99 89.68 683.06
   3 │ 10.77 269.75 1928.6
   4 │ 4.27 122.62 102.83
   5 │ 2.18 178.34 214.79

julia> println(df)
5×3 DataFrame
 Row │ height area volume  
     │ Float64 Float64 Float64 
─────┼───────────────────────────
   1 │ 29.58 273.83 840.17
   2 │ 18.99 89.68 683.06
   3 │ 10.77 269.75 1928.6
   4 │ 4.27 122.62 102.83
   5 │ 2.18 178.34 214.79

```
