Constructing multi-dimensional array from existing ones

Hi, I’m a new user from Python. I’m trying to do something like:

a, b = np.random.rand(5,5), np.random.rand(5,5)
c = np.array([a, b])

to obtain an array with dimension (2, 5, 5). But the following code seems not working as expected:

a, b = rand(5,5), rand(5,5)
c = Array([a, b])

In this way c seems to be an array with 2 elements with each element a (5, 5) array.

I know this is a silly question, but I can’t find any solution online, probably due to wrong keywords.
I’m curious why this is the behavior in Julia and what is the correct way to achieve my goal. Thank you in advance!

You may be looking for

permutedims(cat(a, b; dims = 3), (3, 1, 2))

You can read

https://docs.julialang.org/en/v1/manual/arrays/#Concatenation-1

but the whole array chapter is worth reading.

1 Like

Imho it makes most sense to change your algorithm to concatenate along the last dimension. In that case just do like @Tamas_Papp suggested, except do

cat(a, b; dims = 3)

The way Julia works is very consistent: [x, y] creates a vector. The first element is x the second element is y. It doesn’t matter what x and y are. What you see is what you get.

On the other hand, I think it would be pretty hard to predict the behaviour of numpy: Shift the dimensions of x and y outwards, then concatenate along the first dimension, oh but only if x and y are numpy arrays. I find this pretty mind-bending.

3 Likes

Indeed, doing just this (without permutedims) and then using a different axis order would be what most Julia programmers would do, unless access patterns suggest something else.

Thanks for your comments! So the behavior is a bit similar to Matlab then. Actually in my case the order of the indices does not matter much, so I’d prefer cat(a, b; dims = 3). But I’ll choose @Tamas_Papp’s answer as the solution because it faithfully produces the behavior I asked in the original question. I think this little snippet is worth being adding to somewhere more visible considering a large fraction of new Julia users is coming from Python. Anyway, my problem is solved and many thanks to you all :grinning:

Actually, in Matlab you get a third behaviour:

>> a = rand(5,5); b = rand(5, 5);
>> size([a, b])
ans =
     5    10

It concatenates along the second dimension, without any dimension-moving, so you end up with a 2D array.

Sure, but cat function can also be used for this purpose:

>>> a = rand(5, 5); b = rand(5, 5);
>>> size(cat(3, a, b))
ans =

   5   5   2

I believe the idea here is quite similar with that in Julia.

Ah, yes, cat is similar in Matlab and Julia, while [...] is different.

There is

https://docs.julialang.org/en/v1/manual/noteworthy-differences/#Noteworthy-differences-from-Python-1

but translating all the different idioms from Python would probably be impossible, and even a 90% attempt would be much longer than the current manual.

It is best to just understand Julia as it is, not in relation to Python. And the manual is the best starting point for most people with prior experience in another language.

1 Like

Actually I find these comparisons quite helpful :blush: . Maybe I’ll compose a PR on this topic when I have some time.

These comparisons are intended to be useful — that’s why they were written. They are just not a substitute to learning about Julia idioms, because they cannot be a comprehensive guide.

1 Like

I just came across the need to do this as well. It would be great if cat had some way to easily specify that you want a dimension inserted. in APL you can concatenate along the 0.5th or 1.5th dimension to add a dimension at the beginning, or between the 1st and 2nd, respectively. So translating to Julia it would be as if:

a, b = rand(3,4), rand(3,4)
size(cat(a, b, dims=0.5)) == (2, 3, 4)
size(cat(a, b, dims=1.5)) == (3, 2, 4)

It feels a little weird to use a floating-point value as a dimension there, but it is a nice compact syntax for doing this sort of thing.

I sure that there are a lot of reasonable options for the syntax, eg dims = 0 => 5, or using nothing for insertion, etc.