T-Vector{m-element Vector{Float64}} into matrix

Hi,

in my code I often use function broadcasting and then end up with objects A like T-element Vector{m-element Vector{Float64}}. I was wondering if there is an easy command to convert A into T-by-m or m-by-T matrix.

It’s not hard to find a work-around by creating an empty T-by-m matrix B and then looping through the ‘vector’ A and assigning each row of B an element

B = zeros(T,m)
for t in 1:T
    B[t,:] = A[t]
end

but I was still wondering if there is faster/less wordy way to do this.

Thank you!

The pre-allocation + loop is a good solution. But you should change the orientation, since Arrays are column-major, so do B[:, t] = A[t] instead.

You can also shave off a bit of time by not initializing B with zeros, and instead do B = Matrix{Float64}(undef, T, m)

If you want less verbose, you can try

B = reduce(hcat, A) 

I suspect it will be slower, but try to benchmark it.

Just use stack.

julia> using Compat: stack

julia> v = [rand(5) for _ ∈ 1:3]
3-element Vector{Vector{Float64}}:
 [0.8171909831508164, 0.15661016815437745, 0.2715396576556385, 0.28385016413585673, 0.5190445250315925]
 [0.7812480311360239, 0.5024262604639554, 0.9024872826844329, 0.80961891784007, 0.8617609639038173]
 [0.7349009228629912, 0.29003919828230684, 0.7731877384653875, 0.36098642491910127, 0.39708957802744305]

julia> stack(v)
5×3 Matrix{Float64}:
 0.817191  0.781248  0.734901
 0.15661   0.502426  0.290039
 0.27154   0.902487  0.773188
 0.28385   0.809619  0.360986
 0.519045  0.861761  0.39709

julia> stack(v, dims=1)
3×5 Matrix{Float64}:
 0.817191  0.15661   0.27154   0.28385   0.519045
 0.781248  0.502426  0.902487  0.809619  0.861761
 0.734901  0.290039  0.773188  0.360986  0.39709

3 Likes

How’s this?

A = [1, 2, 3]
B = [x for x ∈ A, j=1:5]

flip x and j iterations to flip dimensions.

The question is also, why do you end up with a nested array in the first place?
From the top of my head, I could think of two obvious ways

  1. You are using eachslice or something like that
  2. You broadcast a function returning an array

In such cases, there are several libraries like SplitApplyCombine.jl or JuliennedArrays.jl which can split into and recombine from nested arrays, i.e., just like stack already mentioned. Further, I had experimented with a small library JJ.jl which allows to apply functions to smaller dimensional parts of an array and automatically recollects all results into an array:

julia> A = [1 2 3; 4 5 6]
2×3 Matrix{Int64}:
 1  2  3
 4  5  6

julia> foo(x) = x .+ [-1, 1]
foo (generic function with 1 method)

julia> foo.(A)
2×3 Matrix{Vector{Int64}}:
 [0, 2]  [1, 3]  [2, 4]
 [3, 5]  [4, 6]  [5, 7]

julia> using JJ

julia> rank"foo 0"(A)  # Same as stack(foo.(A))
2×2×3 Align{Int64, 3} with eltype Int64:
[:, :, 1] =
 0  3
 2  5

[:, :, 2] =
 1  4
 3  6

[:, :, 3] =
 2  5
 4  7

julia> rank"foo 1"(A)  # same as stack(foo.(eachslice(A; dims=2)))
2×3 Align{Int64, 2} with eltype Int64:
 0  1  2
 5  6  7
1 Like