# Sort vector by frequency

**URL:** <https://discourse.julialang.org/t/sort-vector-by-frequency/14946>\
**Category:** New to Julia\
**Tags:** sort, arrays\
**Created:** [September 14, 2018, 10:14am UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946 "2018-09-14T10:14:20Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![DominiqueMakowski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dominiquemakowski/32/51410_2.png) [@DominiqueMakowski](https://discourse.julialang.org/u/DominiqueMakowski)\
**Post date:** [September 14, 2018, 10:14am UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/1 "2018-09-14T10:14:20Z")

</div>

I am trying to sort a vector of strings by the frequency of tis values.

For instance:

```julia
x = ["a", "b", "b", "c", "c", "c"]

```

Since there are 3 `"c"`, 2 `"b"` and 1 `"a"`, I would like to get a vector of uniques in that order:

```julia
["c", "b", "a"]

```

Currently, I’ve managed to count the existing values:

```julia
using StatsBase

x = ["a", "b", "b", "c", "c", "c"]
string_count = StatsBase.countmap(x)
Dict("c"=>3,"b"=>2,"a"=>1)

```

This returns a dict with frequencies (well, the number of each element), but I am stuck at trying to transform this into a sorted vector of uniques…

I believe one could extract the keys and values as two columns of a dataframe, sort this dataframe by the `number` and then extract the column of `values`, but it seems a bit inefficient…

---

<div class="post-metadata">

**Author:** ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)\
**Post date:** [September 14, 2018, 10:30am UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/2 "2018-09-14T10:30:30Z")

</div>

You can obtain the `keys` and `values` from a `Dict` like so

```julia
keys1 = [k for k in keys(string_count)]
sortperm_vals = sortperm([v for v in values(string_count)])

strings_sorted_by_freq = keys1[sortperm_vals]

```

---

<div class="post-metadata">

**Author:** ![rvasil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvasil/32/3821_2.png) [@rvasil](https://discourse.julialang.org/u/rvasil)\
**Post date:** [September 14, 2018, 10:43am UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/3 "2018-09-14T10:43:55Z")

</div>

```julia
collect(keys(StatsBase.countmap(x)))

```

but maybe `countmap` does not guarantee the order (?), so to sort explicitly, you can:

`collect` from Dict to Array of Pairs, `sort` by anon function returning count descending, get `first.` element from each Pair returned.

Like this:

```julia
string_count = StatsBase.countmap(x)

sortedvals =first.(sort(collect(string_count), by = e -> e[2], rev=true))

```

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [September 14, 2018, 10:55am UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/4 "2018-09-14T10:55:47Z")

</div>

Slightly cleaner:

```julia
using StatsBase

x = ["a", "b", "b", "c", "c", "c"]
string_count = StatsBase.countmap(x)
keys(sort(string_count, by = last, rev=true))

```

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [September 14, 2018, 4:21pm UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/5 "2018-09-14T16:21:47Z")

</div>

Or using FreqTables.jl:

```julia
julia> sort(freqtable(x))
3-element Named Array{Int64,1}
Dim1 │ 
──────┼──
a │ 1
b │ 2
c │ 3

```

---

<div class="post-metadata">

**Author:** ![Rafael\_Brus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael_brus/32/23767_2.png) [@Rafael\_Brus](https://discourse.julialang.org/u/Rafael_Brus)\
**Post date:** [August 28, 2021, 7:02pm UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/6 "2021-08-28T19:02:09Z")

</div>

> [@nalimilan](#):
>
> `freqtable`

How do I get “a” from an array?

```julia
julia> z = sort(freqtable(x))
3-element Named Vector{Int64}
Dim1 │
──────┼──
a │ 1
b │ 2
c │ 3

julia> z[1]
1

```

---

<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:** [August 28, 2021, 10:57pm UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/7 "2021-08-28T22:57:39Z")

</div>

@Rafael_Brus, try this:

```julia
ft = sort(freqtable(x))
names(ft,1)[1]

```

---

<div class="post-metadata">

**Author:** ![rikh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rikh/32/204104_2.png) [@rikh](https://discourse.julialang.org/u/rikh)\
**Post date:** [July 7, 2022, 3:35pm UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/8 "2022-07-07T15:35:38Z")

</div>

Here is a solution without dependencies. Credits to @rvasil for noting the keyword arguments to `sort`.

```julia
function count_unique(V::AbstractVector{T}) where T
    U = unique(V)
    l = length(U)
    counts = Dict{T,Int}(zip(U, zeros(l)))
    for v in V
        counts[v] += 1
    end
    return counts
end

function frequency_sort(V::AbstractVector)
    counts = count_unique(V)
    sorted = sort(collect(counts); by=last, rev=true)
    return first.(sorted)
end

```

Benchmarks (Julia 1.8-rc1):

```julia
julia> using BenchmarkTools

julia> @btime frequency_sort(rand(1:100, 1_000));
  30.355 μs (28 allocations: 24.55 KiB)

julia> @btime frequency_sort(rand(1:100, 100_000));
  2.374 ms (29 allocations: 797.91 KiB)

julia> @btime frequency_sort(rand(1:1000, 100_000));
  2.423 ms (38 allocations: 942.39 KiB)

```

---

<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:** [July 7, 2022, 5:42pm UTC](https://discourse.julialang.org/t/sort-vector-by-frequency/14946/9 "2022-07-07T17:42:13Z")

</div>

> [@yakir12](#):
>
> Slightly cleaner:

Cleaner perhaps, but note that it will not get the correct results for input:

```julia
x = ["a", "b", "b", "c", "c", "c", "d"]

```
