I have two cell arrays, one of them
A is a 27x1 cell, size(A{i}) is 360x180.
B is a 35x1 cell, and size(B{i}) is the same as the above, i.e., 360x180.
How do I stack them together to create a C that has a size of 360x180x62?
Thanks.
I have two cell arrays, one of them
A is a 27x1 cell, size(A{i}) is 360x180.
B is a 35x1 cell, and size(B{i}) is the same as the above, i.e., 360x180.
How do I stack them together to create a C that has a size of 360x180x62?
Thanks.
Do you mean that you have A, B that are vectors (i e. 1-dim arrays) of matrices (i e. 2 dims arrays) and you want to stack them in a 3 dims Array?
Iām not familiar with all these terms, but basically, A has 27 matrices. In Matlab I can call them like this:
A{1}
A{2}
ā¦
A{27}.
What I want to get is a C that stacks up all these 27 matrices as well as the 35 matrices from B, thus producing a matrix with the size of 360x180x62.
Thanks.
If all you want is to concatenate A and B (both vectors where each entry is a matrix) to a C vector containing all the matrices you can use C = vcat(A,B)
, but this will NOT produce a 3 dimensional array, but a nested vector of matrices.
maybe this is what you are looking for
A=rand(360,180,27);
B=rand(360,180,35);
c=[A;;;B]
#or
c=hvncat(3,A,B)
Is this a Matlab or Julia question?
In Julia, there is no such thing as a cell array, though Array{Any, N}
is similar. But assuming you have two vectors of matrices, you can do
C = cat(A..., B...; dims=3)
This looks like a MATLAB question.
In MATLAB, see cat
.
You might vwant something like cat(3, A{:}, B{:})
.
For MATLAB questions in the future see
https://www.mathworks.com/matlabcentral/
This is not a MATLAB help forum.
To clarify, this is a Julia question 100%. My apologies for the confusion. I just used the Matlab ācell arrayā concept to describe the array, as I do not know how it is called within Julia.
Thanks for the recommended solution. Unfortunately, it does not work for me. My Julia would freeze every single time I tried this.
Thanks for the suggestions. However, my A and B are vectors of matrices, instead of 3d arrays.
What is your A
and B
in Julia?
In Julia, I would do this.
julia> begin
A = [zeros(UInt8, 360, 180) for i in 1:27]
B = [zeros(UInt8, 360, 180) for i in 1:35]
end;
julia> C = [A...;;; B... ];
julia> size(C)
(360, 180, 62)
You can access inidivudal matrices as follows.
julia> A[1];
julia> A[27];
julia> B[27];
julia> C[60];
Basically we do not need the concept of cell array in Julia. Itās just an array.
The literal equivalent of a cell array in Julia would be Array{N,Any} where N Array{N, Any} where N
where each position of the array here could be anything.
julia> v = Vector{Any}(undef, 5);
julia> v[1] = 5
5
julia> v[2] = zeros(3,5)
3Ć5 Matrix{Float64}:
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
julia> v[3] = true
true
julia> v[4] = 9.0
9.0
julia> v[5] = Ļ
Ļ = 3.1415926535897...
julia> v
5-element Vector{Any}:
5
[0.0 0.0 ā¦ 0.0 0.0; 0.0 0.0 ā¦ 0.0 0.0; 0.0 0.0 ā¦ 0.0 0.0]
true
9.0
Ļ = 3.1415926535897...
In your case, however, you know all the elements are going to be of type Matrix{Float64}
so we can be more specific.
julia> typeof(A)
Vector{Matrix{UInt8}} (alias for Array{Array{UInt8, 2}, 1})
Iām glad you found a solution, but Iād like to point out that itās a solution to a very different problem than the one described in the Original Post. It shows how to concatenate 3d arrays, but you were asking about vectors of matrices (ācell arrays of matricesā).
My proposed solution concerned itself vectors of matrices. If you feed it 3d arrays, itās no surprise Julia froze, since it would try to compile a function with 4 million input arguments (360 * 180 * 62
).
You are exactly right. I got myself confused. As you mentioned, my A and B are not 3d arrays like the below.
A=rand(360,180,27);
B=rand(360,180,35);
Instead they are vectors of matrices like these:
begin
A = [zeros(UInt8, 360, 180) for i in 1:27]
B = [zeros(UInt8, 360, 180) for i in 1:35]
end;
As a result, your recommended solution as below works the best:
C = cat(A..., B...; dims=3)
Sorry for the confusion, but Iām glad this post now has solutions for both 3d arrays and vectors of arrays.
Please donāt recommend to beginners that they splat arrays like this. Youāre just going to cause them problems and pain if they use an array thatās too big since itāll always incur a dynamic dispatch, and it creates large Tuples which can cause the compiler to freak out.
@Leon6 a more scalable way of doing this is with the stack
function:
D = stack(vcat(A, B));
Hereās a performance comparison:
julia> begin
A = [zeros(UInt8, 360, 180) for i in 1:27]
B = [zeros(UInt8, 360, 180) for i in 1:35]
end;
julia> @btime C = cat($A..., $B...; dims=3);
2.071 ms (573 allocations: 3.88 MiB)
julia> @btime D = stack(vcat($A, $B));
104.551 Ī¼s (3 allocations: 3.83 MiB)
Easy 20x improvement.
Iād like to point out that stack
isnāt available in Julia yet, so think there should be a big disclaimer on that.
Also, I have frequently found that splatting performs annoyingly well, for some reason, even for large arrays. The performance characteristics of splatting remains a bit of a mystery to me.
Since stack
is unreleased as of Julia 1.8, you need to tell him how to do with pre-Julia 1.9.
stack
is in Compat.jl.
Yes, sorry I misremembered and thought it was in 1.8. The ammended advice is to do (once)
using Pkg
Pkg.add("Compat")
and then once thatās installed, you can do
using Compat: stack
D = stack(vcat(A, B));
begin
A = [rand(360, 180) for _ in 1:27]
B = [rand(360, 180) for _ in 1:35]
end;
using BenchmarkTools
julia> @btime C=hvncat(3, A...,B...);
543.363 ms (20024381 allocations: 397.52 MiB)
julia> @btime reshape(mapreduce(vec,vcat,A), (size(A[1])...,:));
41.736 ms (110 allocations: 186.39 MiB)
julia> @btime C = cat($A..., $B...; dims=3);
6.810 ms (573 allocations: 30.70 MiB)
# cat seems 100X faster than hvncat(!?!?)
using Compat: stack
julia> @btime stack(vcat(A, B));
6.774 ms (3 allocations: 30.65 MiB)
# using copyto! seems faster than stack
julia> @btime begin
C=similar(Array{Float64,3},(size(A[1])...,62));
foreach(k->copyto!($C,1+360*180*(k-1), [A;B][k], 1, 360*180), 1:62)
end
4.009 ms (127 allocations: 30.69 MiB)
julia> @btime foreach(k->copyto!($C,1+360*180*(k-1), [A;B][k], 1, 360*180), 1:62)
3.905 ms (123 allocations: 33.89 KiB)
julia> @btime begin
C=similar(Array{Float64,3},(size(A[1])...,62));
foreach(k->copyto!($C,1+360*180*(k-1), A[k], 1, 360*180), 1:27)
foreach(k->copyto!($C,1+360*180*(k-1), B[k-27], 1, 360*180), 28:62)
end
4.167 ms (65 allocations: 30.65 MiB)
PS
I couldnāt use the copyto!() method which makes use of cartesianindices
Note that your second to last example doesnāt include the allocation of Cā¦