# Shuffling multiple N-arrays over a given dimension

**URL:** <https://discourse.julialang.org/t/shuffling-multiple-n-arrays-over-a-given-dimension/59206>\
**Category:** General Usage\
**Tags:** arrays, random\
**Created:** [April 13, 2021, 2:44pm UTC](https://discourse.julialang.org/t/shuffling-multiple-n-arrays-over-a-given-dimension/59206 "2021-04-13T14:44:21Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [April 13, 2021, 2:44pm UTC](https://discourse.julialang.org/t/shuffling-multiple-n-arrays-over-a-given-dimension/59206/1 "2021-04-13T14:44:21Z")

</div>

Sometimes we have the need to shuffle a given list of arrays over a given dimension, but keeping the relative order on that dimension ( e.g. when we have in machine learning to shuffle features and label matrices over the dimension concerning the observations).  
I hence developed the following function that does that. Do you have comments / ideas on how to improve it ?

```julia
import Random.shuffle
"""
    shuffle(data;dims,rng)

Shuffle a vector of n-dimensional arrays across dimension `dims` keeping the same order between the arrays

# Parameters
- `data`: The vector of arrays to shuffle
- `dims`: The dimension over to apply the shuffle [def: `1`]
- `rng`: An `AbstractRNG` to apply for the shuffle

# Notes
- All the arrays must have the same size for the dimension to shuffle

# Example

julia> a = [1 2 30; 10 20 30]; b = [100 200 300];
julia> (aShuffled, bShuffled) = shuffle([a,b],dims=2)
2-element Vector{Matrix{Int64}}:
 [1 30 2; 10 30 20]
 [100 300 200]
 
"""
function shuffle(data::AbstractArray{T,1};dims=1,rng=Random.GLOBAL_RNG) where T <: AbstractArray
    Ns = [size(m,dims) for m in data]
    length(Set(Ns)) == 1 || @error "In `shuffle(arrays)` all individual arrays need to have the same size on the dimension specified"
    N = Ns[1]
    ridx = Random.shuffle(rng, 1:N)
    out = similar(data)
    for (i,a) in enumerate(data)
       aidx = [collect(1:i) for i in size(a)]
       aidx[dims] = ridx
       out[i] = a[aidx...]
    end
    return out
end
shuffle(rng::AbstractRNG,data::AbstractArray{T,1};dims=1) where T <: AbstractArray = shuffle(data;dims=dims,rng=rng)

```

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [October 27, 2022, 4:24am UTC](https://discourse.julialang.org/t/shuffling-multiple-n-arrays-over-a-given-dimension/59206/2 "2022-10-27T04:24:52Z")

</div>

I now see that this is indeed type piracy as `Random.shuffle` works also on arrays of arrays, with reordening the individual arrays.  
I suppose I should then change its name… suggestions ? “consistentshuffle” ? but it’s long…

---

<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:** [October 27, 2022, 8:19am UTC](https://discourse.julialang.org/t/shuffling-multiple-n-arrays-over-a-given-dimension/59206/3 "2022-10-27T08:19:51Z")

</div>

If I am not mistaken, `mapslices()` and broadcasting could greatly simplify this task:

```julia
a = [1 2 30; 10 20 30]; b = [100 200 300]
Random.seed!(0)
dim = 2
ix = randperm(size(a,dim))
mapslices.(x->x[ix], [a,b], dims=dim)

# result:
2-element Vector{Matrix{Int64}}:
 [2 1 30; 20 10 30]
 [200 100 300]

```
