# What is the role of Ref in this function and why is it faster than the alternative?

**URL:** https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319
**Category:** General Usage
**Tags:** question
**Created:** [June 14, 2023, 8:51am UTC](https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319 "2023-06-14T08:51:10Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Soldalma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soldalma/32/29388_2.png) [@Soldalma](https://discourse.julialang.org/u/Soldalma)
#### Post date: [June 14, 2023, 8:51am UTC](https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319/1 "2023-06-14T08:51:10Z")

</div>

This function converts a categorical vector to an index:

```julia
function convert_factor_to_index(cat_vec::CategoricalVector)::Vector{Int}
        levs = levels(cat_vec)

        int_vec::Vector{Int} = findfirst.(isequal.(cat_vec), Ref(levs))
        #! int_vec = findfirst.([isequal.(catv)[i].(levs) for i in 1:length(levs)])

        return int_vec
    end # convert_factor_to_index

```

An example:

```julia
julia> v = ["A", "B", "C"]
    convert_factor_to_index(categorical(v))
    3-element Vector{Int64}:
    1
    2
    3

```

So the function works, but I am not clear why it needs the `Ref`. (It does not work without it).

Also, it runs much slower with the following line of code:

```julia
int_vec = findfirst.([isequal.(catv)[i].(levs) for i in 1:length(levs)])

```

I understand broadcasting is fast, but does `Ref` also helps to speed up things?

---

<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: [June 14, 2023, 9:40am UTC](https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319/2 "2023-06-14T09:40:25Z")

</div>

Are you maybe looking for the `levelcode` function in `CategoricalArrays`?

```julia
julia> levelcode.(v)
3-element Vector{Int64}:
 1
 2
 3

```

To your other question, no, `Ref` is not speeding up anything, it’s simply required to protect `levs` from broadcasting. You could have equally wrapped it in a single-argument `Tuple` like `(levs, )`.

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [June 14, 2023, 1:13pm UTC](https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319/3 "2023-06-14T13:13:46Z")

</div>

This doesn’t seem right:

> ```julia
> int_vec = findfirst.([isequal.(catv)[i].(levs) for i in 1:length(levs)])
> 
> ```

It’s as if you tried to replace broadcasting with list comprehension, but something went awry. I think you meant something like this:

```julia
int_vec = [findfirst([isequal(cat), levs) for cat in cat_vec]

```

At least that is what the initial broadcast is equivalent to. The `Ref` merely protects the `levs` argument to be broadcast.

---

<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: [June 14, 2023, 1:20pm UTC](https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319/4 "2023-06-14T13:20:06Z")

</div>

Sifting through the available functions, I see that there are `pool()` and `refs()` to get the data of interest from a categorical vector

```julia
julia> using CategoricalArrays, BenchmarkTools

julia> function convert_factor_to_index(cat_vec::CategoricalVector)::Vector{Int}
           levs = levels(cat_vec)
       
           int_vec::Vector{Int} = findfirst.(isequal.(cat_vec), Ref(levs))
           #! int_vec = findfirst.([isequal.(catv)[i].(levs) for i in 1:length(levs)])
       
           return int_vec
       end # convert_factor_to_index
convert_factor_to_index (generic function with 1 method)

julia> v = ["A", "B", "C"]
3-element Vector{String}:
 "A"
 "B"
 "C"

julia> @btime convert_factor_to_index(categorical(v))
  378.325 ns (12 allocations: 944 bytes)
3-element Vector{Int64}:
 1
 2
 3

julia> @btime CategoricalArrays.refs(categorical($v))
  285.036 ns (10 allocations: 848 bytes)
3-element Vector{UInt32}:
 0x00000001
 0x00000002
 0x00000003

julia> @btime CategoricalArrays.pool(categorical($v))
  286.594 ns (10 allocations: 848 bytes)
CategoricalPool{String, UInt32}(["A", "B", "C"])

```

---

<div class="post-metadata">

### Author: ![Soldalma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soldalma/32/29388_2.png) [@Soldalma](https://discourse.julialang.org/u/Soldalma)
#### Post date: [June 14, 2023, 1:51pm UTC](https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319/5 "2023-06-14T13:51:39Z")

</div>

The code I proposed works if one replaces ‘catv’ with ‘cat\_vec’:

```julia
v = ["A", "B", "C"]
cat_vec = categorical(v)
levs = levels(cat_vec)
int_vec = findfirst.([isequal.(cat_vec)[i].(levs) for i in 1:length(levs)])
3-element Vector{Int64}:
 1
 2
 3

```

---

<div class="post-metadata">

### Author: ![Soldalma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soldalma/32/29388_2.png) [@Soldalma](https://discourse.julialang.org/u/Soldalma)
#### Post date: [June 14, 2023, 1:53pm UTC](https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319/6 "2023-06-14T13:53:22Z")

</div>

That is what I needed. Thanks.

---

<div class="post-metadata">

### Author: ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)
#### Post date: [June 14, 2023, 3:15pm UTC](https://discourse.julialang.org/t/what-is-the-role-of-ref-in-this-function-and-why-is-it-faster-than-the-alternative/100319/7 "2023-06-14T15:15:41Z")

</div>

> [@Soldalma](#):
>
> `isequal.(cat_vec)[i]`

This is definitely less efficient than `isequal(cat_vec[i])`.
