Mike Vella
Mike Vella

Reputation: 10575

slicing multidimensional Julia arrays not symmetric

Take the following 2x2x2 Julia array:

julia> a
2x2x2 Array{Int32,3}:
[:, :, 1] =
 1  3
 2  4

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

I was surprised to notice that slicing along different dimensions gives non-symmetric results:

julia> a[:,:,1]
2x2 Array{Int32,2}:
 1  3
 2  4

vs:

julia> a[:,1,:]
2x1x2 Array{Int32,3}:
[:, :, 1] =
 1
 2

[:, :, 2] =
 2
 3

Can someone explain what's going on here? I come from a numpy/MATLAB background and this behaviour is extremely odd to me.

Upvotes: 2

Views: 1156

Answers (3)

mbauman
mbauman

Reputation: 31342

This has now changed with Julia 0.5. Slicing is now "symmetric" and a[:,:,1] == a[:,1,:]. All dimensions indexed by scalars are now dropped, and, in general, the dimensionality of the output is the sum of the dimensionalities of the indices.

Upvotes: 2

tholy
tholy

Reputation: 12179

If you come from a Matlab background, this shouldn't be too surprising, since Matlab works the same way:

>> a = reshape(1:8, 2, 2, 2)

a(:,:,1) =

     1     3
     2     4


a(:,:,2) =

     5     7
     6     8

>> b = a(:,:,1)

b =

     1     3
     2     4

>> ndims(b)

ans =

     2

>> c = a(:,1,:)

c(:,:,1) =

     1
     2


c(:,:,2) =

     5
     6

>> ndims(c)

ans =

     3

In both Julia and Matlab, it's not an error to add extra 1s when you index; you can still write b[2,2,1] even though b is a 2d object.

Finally, if you want something that acts much more like numpy, consider (in Julia) using slice:

julia> c = slice(a, :, 1, :)
2x2 SubArray{Int64,2,Array{Int64,3},(Range1{Int64},Int64,Range1{Int64})}:
 1  5
 2  6

julia> c = slice(a, :, 1:1, :)
2x1x2 SubArray{Int64,3,Array{Int64,3},(Range1{Int64},Range1{Int64},Range1{Int64})}:
[:, :, 1] =
 1
 2

[:, :, 2] =
 5
 6

You'll get a SubArray back (an array view), which has some slightly different properties but in the long term is likely to be returned by most indexing operations. Alternatively, if you prefer an array you can call squeeze or reshape on the return value of a[:,1,:] to get the result you want.

Upvotes: 4

ivarne
ivarne

Reputation: 3783

Currently Julia drops trailing singular dimensions when slicing, and it does it consistently for any dimension. I think this is just the generalization of how I want a row vector (1*n) instead of a regular vector (n) when slicing a matrix row-vise.

julia> a = [1 2; 3 4]
2x2 Array{Int64,2}:
 1  2
 3  4

julia> a[:,1]
2-element Array{Int64,1}:
 1
 3

julia> a[1,:]
1x2 Array{Int64,2}:
 1  2 

Unlike matlab (and partially numpy), Julia has scalar values and 1d vectors so the instead of just a general nd matrix type. I do not think you are the first to be confused by this property. I remember seeing suggestions to drop all singular dimensions, and require you to do a[1:1,:] to get a row vector, but I am not sure that would be any better.

Upvotes: 2

Related Questions