# Is there a function similar to numpy unique with inverse?

**URL:** <https://discourse.julialang.org/t/is-there-a-function-similar-to-numpy-unique-with-inverse/80949>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 12, 2022, 11:01am UTC](https://discourse.julialang.org/t/is-there-a-function-similar-to-numpy-unique-with-inverse/80949 "2022-05-12T11:01:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Minimum-Pollution-96](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@Minimum-Pollution-96](https://discourse.julialang.org/u/Minimum-Pollution-96)\
**Post date:** [May 12, 2022, 11:01am UTC](https://discourse.julialang.org/t/is-there-a-function-similar-to-numpy-unique-with-inverse/80949/1 "2022-05-12T11:01:56Z")

</div>

In python numpy, I can write my code as,

```python
unique_vals, reverse_ids = np.unique(vals, return_inverse=True)

```

Here, `reverse_ids` is the list of indices such that,

```julia
unique_vals[reverse_ids] == vals

```

Is there something similar available in Julia? As far as I know, there is a unique function but it doesn’t have any such parameters.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [May 12, 2022, 11:51am UTC](https://discourse.julialang.org/t/is-there-a-function-similar-to-numpy-unique-with-inverse/80949/2 "2022-05-12T11:51:40Z")

</div>

I’m not sure how that works in numpy in the first place - is `unique_vals` not a proper numpy array but rather some special construct? `unique` in julia doesn’t give you a slice or view into the existing array, it creates a new array with the unique values of the old array. Indexing with indices relating to `vals` into that doesn’t really make a whole lot of sense to me…

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [May 12, 2022, 11:55am UTC](https://discourse.julialang.org/t/is-there-a-function-similar-to-numpy-unique-with-inverse/80949/3 "2022-05-12T11:55:14Z")

</div>

Ah, I think I got what it’s doing from [the numpy documentation](https://numpy.org/doc/stable/reference/generated/numpy.unique.html). Seems like this should work for you:

```julia
julia> a = [1,2,6,4,2,3,2];

julia> u = unique(a)
5-element Vector{Int64}:
 1
 2
 6
 4
 3

julia> indices = [findfirst(==(ux), u) for ux in a]
7-element Vector{Int64}:
 1
 2
 3
 4
 2
 5
 2

julia> u[indices] == a
true

```

But no, that’s not built in as far as I know. Seems kind of niche, when you usually have `vals` already anyway 🤷

---

<div class="post-metadata">

**Author:** ![non-Jedi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/non-jedi/32/3645_2.png) [@non-Jedi](https://discourse.julialang.org/u/non-Jedi)\
**Post date:** [May 12, 2022, 11:56am UTC](https://discourse.julialang.org/t/is-there-a-function-similar-to-numpy-unique-with-inverse/80949/4 "2022-05-12T11:56:56Z")

</div>

I’m not aware of such functionality built into `Base` or any mainstream packages. You can implement it yourself quite easily. Not the necessarily the most efficient, but it should be significantly faster than @Sukera’s solution (which has the advantage of not being overengineered for simple cases):

```
   function unique_ids(itr)
     v = Vector{eltype(itr)}()
     d = Dict{eltype(itr), Int}()
     revid = Vector{Int}()
     for val in itr
       if haskey(d, val)
         push!(revid, d[val])
       else
         push!(v, val)
         d[val] = length(v)
         push!(revid, length(v))
       end
     end
     (v, revid)
   end

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [May 12, 2022, 11:58am UTC](https://discourse.julialang.org/t/is-there-a-function-similar-to-numpy-unique-with-inverse/80949/5 "2022-05-12T11:58:43Z")

</div>

> [@non-Jedi](#):
>
> (which has the advantage of not being overengineered for simple cases)

I wasn’t sure how far to optimize either - could be that numpy does some funky things like restoring dimensions as well 🤷

---

<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:** [May 12, 2022, 12:11pm UTC](https://discourse.julialang.org/t/is-there-a-function-similar-to-numpy-unique-with-inverse/80949/6 "2022-05-12T12:11:16Z")

</div>

See also:

- [Unique (indices) method similar to MATLAB](https://discourse.julialang.org/t/unique-indices-method-similar-to-matlab/34446)
- [indices of unique elements of vector in Julia - Stack Overflow](https://stackoverflow.com/questions/50899973/indices-of-unique-elements-of-vector-in-julia)
- [https://groups.google.com/g/julia-users/c/205gVuPuZFU?pli=1](https://groups.google.com/g/julia-users/c/205gVuPuZFU?pli=1)
- [https://github.com/JuliaLang/julia/issues/1845](https://github.com/JuliaLang/julia/issues/1845)

And in particular [this solution](https://discourse.julialang.org/t/unique-indices-method-similar-to-matlab/34446/3):

```julia
uniqueinds(x) = unique(i -> x[i], eachindex(x))

```

However, this isn’t quite the same thing: it’s equivalent to [`return_index=True` in `numpy.unique`](https://numpy.org/doc/stable/reference/generated/numpy.unique.html), not `return_inverse=True`.
