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):
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?
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.
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. RecursiveArrayTools has the slightly weird feature that linear indexing doesnβt do what youβd expect for a 3-array: B[1] isa Matrix.
You can use that here, with a reshape:
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 it sounds like someone just has to get around to writing it.