Reputation: 85
I'm using Julia comprehension to achieve the following:
Given a matrix
A = [1 2; 3 4]
,
I want to expand it into
B =
[1, 1, 1, 2, 2;
1, 1, 1, 2, 2;
1, 1, 1, 2, 2;
3, 3, 3, 4, 4;
3, 3, 3, 4, 4].
Right now I'm doing this with
ns = [3, 2]
B = [fill(B[i, j], ns[i], ns[j]) for i = 1:2, j = 1:2]
However, instead of getting a 5x5 matrix, it gives me:
2×2 Array{Array{Int64,2},2}:
[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]
So how should I convert this 2d array of matrices to a 2d matrix? Or are there other ways to do the expansion I need?
Upvotes: 2
Views: 553
Reputation: 69899
Here are two example ways how you could do it (the first one uses your approach, the second one does not generate intermediate matrices):
julia> A = [1 2; 3 4]
2×2 Array{Int64,2}:
1 2
3 4
julia> ns = [3, 2]
2-element Array{Int64,1}:
3
2
julia> hvcat(2, [fill(A[j, i], ns[j], ns[i]) for i = 1:2, j = 1:2]...)
5×5 Array{Int64,2}:
1 1 1 2 2
1 1 1 2 2
1 1 1 2 2
3 3 3 4 4
3 3 3 4 4
julia> nsexpand = reduce(vcat, (fill(k, ns[k]) for k in axes(ns, 1)))
5-element Array{Int64,1}:
1
1
1
2
2
julia> [A[i, j] for i in nsexpand, j in nsexpand]
5×5 Array{Int64,2}:
1 1 1 2 2
1 1 1 2 2
1 1 1 2 2
3 3 3 4 4
3 3 3 4 4
EDIT
Here is an additional example:
julia> A = [1 4 7 10
2 5 8 11
3 6 9 12]
3×4 Array{Int64,2}:
1 4 7 10
2 5 8 11
3 6 9 12
julia> hvcat(3, A...)
4×3 Array{Int64,2}:
1 2 3
4 5 6
7 8 9
10 11 12
julia> vec(A)
12-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
10
11
12
So:
hvcat
has h
before v
so it takes elements row-wiseso in effect you have to create the temporary array as a transpose of your target (because hvcat
will take its columns to create rows of a target arrays). Actually this is only a coincidence - hvcat
does not know that your original elements were storing in a matrix (it takes them as positional arguments to the call and at that time the fact that they were stored in a matrix is lost due to ...
operation).
Upvotes: 2