# Turn vector of matrices into 3D array

**URL:** <https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777>\
**Category:** New to Julia\
**Tags:** question, array, vector, matrices, reshaping\
**Created:** [October 14, 2021, 9:08pm UTC](https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777 "2021-10-14T21:08:34Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![hannesbecher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hannesbecher/32/28382_2.png) [@hannesbecher](https://discourse.julialang.org/u/hannesbecher)\
**Post date:** [October 14, 2021, 9:08pm UTC](https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777/1 "2021-10-14T21:08:35Z")

</div>

Background: My simulation program returns a 4x4 matrix. Running many replicates using `map()` or a vector comprehension, I get a long vector of small matrices. Similar to `[rand(4, 4) for _ in 1:10000]`.

Question: Is there a one-line way to turn a vector of 10,000 small (4x4) matrices into a 3D array (size 4x4x1000)? If the vector was short, one could do: `cat(vector_of_vectors..., dims=3)`. But that fails for longer vectors as pointed out by others before.

The analogous problem of turning a vector of vectors into a matrix is easy: `reduce(hcat, vector_of_vectors)`.

For my matrices, I tried `reduce(cat, vector_of_matrices)` and `reduce(x -> cat(x, dims=3), vector_of_matrices)` without success. At the moment, I use this function, which works and is fast (`mv` being the vector of matrices):

```julia
function matVec2Arr(mv)
    a = zeros(size(mv[1])..., length(mv))
    for i in 1:length(mv)
        a[:,:,i] = mv[i]
    end
    return a
end

```

I am just wondering is there a more ‘elegant’ way?

Thanks,  
Hannes

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 14, 2021, 9:11pm UTC](https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777/2 "2021-10-14T21:11:20Z")

</div>

If the matrices are always 4x4 (thus small) use static arrays and store a vector of these, the memory layout will be the same of a 3D array and a “reinterpret” should do the trick.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 14, 2021, 9:14pm UTC](https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777/3 "2021-10-14T21:14:11Z")

</div>

```julia
julia> @benchmark reduce(hcat, b) setup=b=[rand(4, 4) for _ in 1:10000]
BenchmarkTools.Trial: 3898 samples with 1 evaluation.
 Range (min … max): 158.440 μs … 5.706 ms ┊ GC (min … max): 0.00% … 93.17%
 Time (median): 242.868 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 327.088 μs ± 232.752 μs ┊ GC (mean ± σ): 16.53% ± 18.96%

    ▁▇█▅▅▃▃▃▃▂▁▁ ▁ ▁ ▁
  ▅▅███████████████▇▆▆▆▅▃▂▂▂▂▃▄▄▅▃▂▄▂▄▅▆█▄▆▆▆██▆▇▆▆▅▆▅▆▃▄▅▄▄▅▄▅ █
  158 μs Histogram: log(frequency) by time 1.22 ms <

 Memory estimate: 1.22 MiB, allocs estimate: 2.

```

this is fine (non-stipid), see the allocation

---

<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 14, 2021, 9:23pm UTC](https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777/4 "2021-10-14T21:23:28Z")

</div>

`TensorCast` makes such operations easy one-liners:

```julia
using TensorCast
m = [rand(4, 4) for _ in 1:10_000]
@cast M[i,j,k] := m[k][i,j] # := returns a view

```

It returns `M` which is `4x4x10_000`

NB:  
_I wish this was the default language._

---

<div class="post-metadata">

**Author:** ![zdenek\_hurak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zdenek_hurak/32/53118_2.png) [@zdenek\_hurak](https://discourse.julialang.org/u/zdenek_hurak)\
**Post date:** [October 15, 2021, 12:07am UTC](https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777/5 "2021-10-15T00:07:58Z")

</div>

Consider [RecursiveArrayTools](https://github.com/SciML/RecursiveArrayTools.jl):

```julia
julia> using RecursiveArrayTools

julia> A = [rand(2,3) for _=1:4]
4-element Vector{Matrix{Float64}}:
 [0.35766183647954497 0.00945510515311243 0.18756680509300394; 0.9738104612662519 0.10918176238450261 0.7844365367234503]
 [0.8572574873275078 0.606234830814707 0.8911587693644292; 0.29714178204328334 0.34785399506946235 0.4215022402770998]
 [0.31381806075696206 0.09938494049668578 0.33507384871214696; 0.8384919930451804 0.9773745902770696 0.5043700409936012]
 [0.7990079554473333 0.39911052428069627 0.49464323002688526; 0.057411978409010134 0.39387907129167 0.28244091355499146]

julia> B = VectorOfArray(A)
VectorOfArray{Float64,3}:
4-element Vector{Matrix{Float64}}:
 [0.35766183647954497 0.00945510515311243 0.18756680509300394; 0.9738104612662519 0.10918176238450261 0.7844365367234503]
 [0.8572574873275078 0.606234830814707 0.8911587693644292; 0.29714178204328334 0.34785399506946235 0.4215022402770998]
 [0.31381806075696206 0.09938494049668578 0.33507384871214696; 0.8384919930451804 0.9773745902770696 0.5043700409936012]
 [0.7990079554473333 0.39911052428069627 0.49464323002688526; 0.057411978409010134 0.39387907129167 0.28244091355499146]

julia> B[1,2,3]
0.09938494049668578

```

There is also [ArraysOfArrays.jl](https://juliaarrays.github.io/ArraysOfArrays.jl/stable/) offering `VectorOfArrays` type, but I have not explored it.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [October 15, 2021, 3:06am UTC](https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777/6 "2021-10-15T03:06:44Z")

</div>

I think ArraysOfArrays solves the opposite problem, i.e. it’s like `eachslice` not like `cat`. There is a small zoo of packages for doing `cat`-like things, my summary of all the ones I found is [here](https://github.com/mcabbott/LazyStack.jl#other-packages). RecursiveArrayTools has the slightly weird feature that linear indexing doesn’t do what you’d expect for a 3-array: `B[1] isa Matrix`.

> [@hannesbecher](#):
>
> The analogous problem of turning a vector of vectors into a matrix is easy: `reduce(hcat, vector_of_vectors)` .

You can use that here, with a reshape:

```julia
julia> A = [rand(4, 4) for _ in 1:10000];

julia> @time B = reduce(hcat, A); summary(B) # done efficiently
  0.000543 seconds (2 allocations: 1.221 MiB)
"4×40000 Matrix{Float64}"

julia> C = reshape(B, 4, 4, :); summary(C) # almost free
"4×4×10000 Array{Float64, 3}"

julia> C[1,2,3] == A[3][1,2]
true

julia> @time C == reduce((x,y) -> cat(x, y, dims=3), A) # done pairwise, slow!
  0.193491 seconds (262.96 k allocations: 396.856 MiB, 9.68% gc time, 28.20% compilation time)
true

```

Although this reshape doesn’t work beyond matrices, and it would be convenient to have a specific function. In [julia#21672](https://github.com/JuliaLang/julia/issues/21672) it sounds like someone just has to get around to writing it.

---

<div class="post-metadata">

**Author:** ![hannesbecher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hannesbecher/32/28382_2.png) [@hannesbecher](https://discourse.julialang.org/u/hannesbecher)\
**Post date:** [October 18, 2021, 8:14pm UTC](https://discourse.julialang.org/t/turn-vector-of-matrices-into-3d-array/69777/7 "2021-10-18T20:14:20Z")

</div>

> [@mcabbott](#):
>
> `reduce((x,y) -> cat(x, y, dims=3), A)`

This is what I was looking for.  
Great to know that

```julia
B = reduce(hcat, A);
C = reshape(B, 4, 4, :);

```

is more efficient.
