TL;DR: I am trying to understand why Matrixes cannot index Vector objects in Julia. Apparently, a vector can index a matrix (see below), but the reverse is not legal. I want to understand the behavior because (1) I don't understand why it does happen and (2) I assume this is preventing the programmer from screwing things up, but I cannot see what this behavior is protecting the programmer against. Thank you very much.
Consider the following arrays.
julia> x_vector = [3 ; 2 ; 1]
3-element Vector{Int64}:
3
2
1
julia> x_matrix = [3 ; 2 ; 1;;]
3×1 Matrix{Int64}:
3
2
1
julia> y_vector = [1 ,0 ,0]
3-element Vector{Int64}:
1
0
0
julia> y_matrix = [1; 0; 0;;]
3×1 Matrix{Int64}:
1
0
0
Now, I will use the y
arrays to index the x
arrays selecting the value that contains a 1 in the y
arrays.
Below I listed the trivial cases (i.e., matrix indexing matrix and a vector indexing a vector)
julia> x_matrix[isone.(y_matrix)]
1-element Vector{Int64}:
3
julia> x_matrix[isone.(y_vector)]
1-element Vector{Int64}:
3
Apparently, I CAN use a vector to index a matrix.
julia> x_matrix[isone.(y_vector)]
1-element Vector{Int64}:
3
However, I CANNOT use a matrix to index a vector, even though they have the same dimensions (do they?).
x_vector[isone.(y_matrix)]
ERROR: BoundsError: attempt to access 3-element Vector{Int64} at index [3×1 BitMatrix]
Stacktrace:
[1] throw_boundserror(A::Vector{Int64}, I::Tuple{Base.LogicalIndex{Int64, BitMatrix}})
@ Base .\abstractarray.jl:691
[2] checkbounds
@ .\abstractarray.jl:656 [inlined]
[3] _getindex
@ .\multidimensional.jl:838 [inlined]
[4] getindex(A::Vector{Int64}, I::BitMatrix)
@ Base .\abstractarray.jl:1218
[5] top-level scope
@ C:\Users\index_matrix_vector.jl:34
[6] eval
@ .\boot.jl:373 [inlined]
CodePudding user response:
If you use integer indexing passing a matrix to index is allowed:
julia> a = [1, 2, 3]
3-element Vector{Int64}:
1
2
3
julia> m = [1 2
3 1]
2×2 Matrix{Int64}:
1 2
3 1
julia> a[m]
2×2 Matrix{Int64}:
1 2
3 1
However, in your examples you use Bool
indexing, which is special as you can check in https://docs.julialang.org/en/v1/manual/arrays/#Logical-indexing.
As you can read there:
A logical index must be a vector of the same length as the dimension it indexes into, or it must be the only index provided and match the size and dimensionality of the array it indexes into.
This restriction follows the logic you have signaled - it is for safety. Now you might ask why for higher dimensional arrays both vector and array indexing is allowed.
My understanding of the reason is that this conceptually matches two ways that arrays in Julia are allowed to be indexed:
- linear indexing (you pass one number when indexing) - this maps to indexing with a vector of
Bool
in your case - normal indexing (you pass as many indices as you have dimensions in your array) - this maps with indexing with an array of
Bool
whose shape matches the shape of indexed array. You could - as the documentation states pass a vector ofBool
indexes for each dimension of your array separately