# Repeating (with function repeat) array elements using a vector of numbers

**URL:** <https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435>\
**Category:** General Usage\
**Created:** [March 3, 2019, 9:40pm UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435 "2019-03-03T21:40:39Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![keeler](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/keeler/32/7303_2.png) [@keeler](https://discourse.julialang.org/u/keeler)\
**Post date:** [March 3, 2019, 9:40pm UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/1 "2019-03-03T21:40:39Z")

</div>

I would like to take a vector, x, and create a new vector, y, by repeating each element in x a number of times, where each number is an element of another vector v.

For example: x=[0.1; 0.6; 0.5]; v=[3; 1; 2]; then the resulting vector would be y=[0.1;0.1;0.1;0.6;0.5;0.5].

I couldn’t find a nice way to do this.

In MATLAB, R or NumPy, you would do the following  
y=repelem(x,v);

y=rep(x,v);

import numpy as np; #NumPy package for arrays, random number generation, etc  
y=np.repeat(x,v);

My workaround is not very elegant and uses a for-loop:

```julia
x=[0.1; 0.6; 0.5];
v=[3; 1; 2];

indexLast=(cumsum(v));
indexFirst=ones(size(indexLast));
indexFirst[2:end]=indexFirst[2:end]+indexLast[1:end-1];
#need to convert floats to integers for indices
indexFirst=floor.(Int,indexFirst);indexLast=floor.(Int,indexLast);
y=zeros(indexLast[end],1); #initiate arrays
for ii=1:length(x)
    #Note need .= for assignment
    y[indexFirst[ii]:indexLast[ii]].=x[ii];
end

```

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 3, 2019, 9:43pm UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/2 "2019-03-03T21:43:32Z")

</div>

One option:

```julia
julia> x=[0.1; 0.6; 0.5]; v=[3; 1; 2];

julia> vcat(fill.(x, v)...)
6-element Array{Float64,1}:
 0.1
 0.1
 0.1
 0.6
 0.5
 0.5

```

---

<div class="post-metadata">

**Author:** ![keeler](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/keeler/32/7303_2.png) [@keeler](https://discourse.julialang.org/u/keeler)\
**Post date:** [March 4, 2019, 1:07am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/3 "2019-03-04T01:07:33Z")

</div>

> [@bennedich](#):
>
> vcat

I didn’t know the fill function. That works. Thanks a lot.

---

<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 4, 2019, 3:46am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/4 "2019-03-04T03:46:28Z")

</div>

> [@keeler](#):
>
> I would like to take a vector, x, and create a new vector, y, by repeating each element in x a number of times, where each number is an element of another vector v.

You could also just use repeated `push!` calls:

```julia
z = eltype(x)[]
sizehint!(z, sum(v))
for (x,n) in zip(x,v), i = 1:n 
    push!(z, x)
end

```

This is slightly more verbose than the `fill` solution, but doesn’t allocate any temporary arrays and avoids splatting lots of arguments, though you can [avoid the latter with `reduce(vcat, fill.(x, v))`](https://github.com/JuliaLang/julia/pull/27188).

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [March 4, 2019, 4:18am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/5 "2019-03-04T04:18:17Z")

</div>

I could have sworn there was a function like this was in StatsBase, but I can never remember its name. Its inverse, `counts`, lives there… did it move? Or is my memory foggy?

---

<div class="post-metadata">

**Author:** ![keeler](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/keeler/32/7303_2.png) [@keeler](https://discourse.julialang.org/u/keeler)\
**Post date:** [March 4, 2019, 4:42am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/6 "2019-03-04T04:42:53Z")

</div>

I was surprised you couldn’t do it with the “repeat” function, particularly given it’s fairly easy in three other popular scientific programming languages.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [March 4, 2019, 5:09am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/7 "2019-03-04T05:09:47Z")

</div>

I think it’s `Base.repeat` which is defined for `AbstractDataFrames` in DataFrames.jl

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 4, 2019, 6:26am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/8 "2019-03-04T06:26:16Z")

</div>

> [@stevengj](#):
>
> you can avoid the latter with `reduce(vcat, fill.(x, v))`

I was excited to see this PR, but I don’t see much of a performance gain… am I missing something? Has splatting been optimized too?

```julia
julia> x,v = rand(100), rand(1:100, 100);

julia> @btime vcat(fill.($x, $v)...);
  10.422 μs (103 allocations: 87.75 KiB)

julia> @btime reduce(vcat, fill.($x, $v));
  10.075 μs (103 allocations: 87.75 KiB)

```

Also, the repeated `push!` is a lot slower:

```julia
function repeat_push(x, v)
    z = eltype(x)[]
    sizehint!(z, sum(v))
    for (x,n) in zip(x,v), i = 1:n
        push!(z, x)
    end
    return z
end

julia> @btime repeat_push($x, $v);
  28.948 μs (2 allocations: 38.83 KiB)

```

The reason for this is that every call to `push!` does a ccall, which not only is slow by itself, but also prevents all kinds of optimizations (in this case SIMDing the inner loop). By pre-allocating and indexing, massive speedups are possible:

```julia
function repeat_prealloc(x, v)
    z = similar(x, sum(v))
    i = 0
    for (x,n) in zip(x,v), k = 1:n
        @inbounds z[i += 1] = x
    end
    return z
end

julia> @btime repeat_prealloc($x, $v);
  2.282 μs (2 allocations: 38.77 KiB)

```

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [March 4, 2019, 9:57am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/9 "2019-03-04T09:57:10Z")

</div>

I believe it is [`StatsBase.inverse_rle`](http://juliastats.github.io/StatsBase.jl/stable/misc.html#StatsBase.inverse_rle)

EDIT:

It basically corresponds to the fast `repeat_prealloc` above.

```julia
julia> @btime repeat_prealloc($x, $v);
  3.686 μs (2 allocations: 39.33 KiB)

julia> @btime inverse_rle($x, $v);
  3.625 μs (2 allocations: 39.33 KiB)

```

---

<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:** [March 4, 2019, 9:26pm UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/10 "2019-03-04T21:26:58Z")

</div>

Also see this PR, which is almost finished:  
[https://github.com/JuliaLang/julia/pull/29560](https://github.com/JuliaLang/julia/pull/29560)

---

<div class="post-metadata">

**Author:** ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)\
**Post date:** [March 5, 2019, 7:08am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/11 "2019-03-05T07:08:04Z")

</div>

> [@stevengj](#):
>
> This is slightly more verbose than the `fill` solution, but doesn’t allocate any temporary arrays

You can also avoid allocation of temporaries using FillArrays.jl:

```julia
julia> using FillArrays, BenchmarkTools

julia> vf(x,v) = vcat(fill.(x, v)...)
vf (generic function with 1 method)

julia> vF(x,v) = vcat(Fill.(x, v)...)
vF (generic function with 1 method)

julia> x=[0.1; 0.6; 0.5]; v=[3; 1; 2];

julia> @btime vf(x,v)
  198.697 ns (5 allocations: 544 bytes)
6-element Array{Float64,1}:
 0.1
 0.1
 0.1
 0.6
 0.5
 0.5

julia> @btime vF(x,v)
  166.403 ns (5 allocations: 352 bytes)
6-element Array{Float64,1}:
 0.1
 0.1
 0.1
 0.6
 0.5
 0.5

```

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 5, 2019, 7:49am UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/12 "2019-03-05T07:49:55Z")

</div>

I’m seeing slightly worse performance however for the larger example above:

```julia
julia> using FillArrays, BenchmarkTools

julia> x,v = rand(100), rand(1:100, 100);

julia> @btime vcat(fill.($x, $v)...);
  10.765 μs (103 allocations: 96.70 KiB)

julia> @btime vcat(Fill.($x, $v)...);
  13.433 μs (206 allocations: 54.23 KiB)

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 5, 2019, 12:58pm UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/13 "2019-03-05T12:58:52Z")

</div>

That’s probably the penalty from splatting so many values into separate function arguments.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [March 5, 2019, 2:40pm UTC](https://discourse.julialang.org/t/repeating-with-function-repeat-array-elements-using-a-vector-of-numbers/21435/14 "2019-03-05T14:40:50Z")

</div>

With `reduce` and `FillArrays` the performance is quite good

```julia
julia> using FillArrays, BenchmarkTools

julia> x,v = rand(100), rand(1:100, 100);

julia> @btime vcat(fill.($x, $v)...);
  9.296 μs (103 allocations: 80.70 KiB)

julia> @btime vcat(Fill.($x, $v)...);
  9.349 μs (206 allocations: 46.42 KiB)

julia> @btime reduce(vcat,Fill.($x, $v));
  3.760 μs (3 allocations: 36.97 KiB)

```
