Xward
Xward

Reputation: 85

Julia comprehension: convert a 2d array of matrices to a 2d matrix

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

Answers (1)

Bogumił Kamiński
Bogumił Kamiński

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:

  • the first argument tells you how how many columns you want to produce
  • hvcat has h before v so it takes elements row-wise
  • however arrays store columns col-wise

so 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

Related Questions