Reputation: 10575
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
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
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 1
s 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
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