user3303504
user3303504

Reputation: 555

Julia matrix row becomes a column during indexing

Issue: When building a matrix out of single rows, Julia interprets them as columns instead.

julia> a = [1 2 3; 4 5 6; 7 8 9]
3×3 Matrix{Int64}:
 1  2  3
 4  5  6
 7  8  9

julia> b = [a[1:2,:]; a[1:2,:]]
4×3 Matrix{Int64}:
 1  2  3
 4  5  6
 1  2  3
 4  5  6

julia> c = [a[1,:]; a[1,:]]
6-element Vector{Int64}:
 1
 2
 3
 1
 2
 3

How to fix this?

Upvotes: 1

Views: 343

Answers (3)

user3303504
user3303504

Reputation: 555

Solution: Although it may feel a bit perplexing, its because the type has changed from a matrix into a vector. To keep the type the same you'll need to select from your desired row, to your desired row in a similar manner to the second line of code in your example.

julia> c = [a[1:1,:]; a[1:1,:]]
2×3 Matrix{Int64}:
 1  2  3
 1  2  3

Upvotes: 2

Ben Francis
Ben Francis

Reputation: 139

The root issue here has everything to do with how a gets indexed and what gets returned by the indexing operation. From the Julia docs on indexing arrays:

All dimensions indexed with scalars are dropped.

The : operator produces a range, i.e., a vector of indices. So, for example,

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

julia> a[1:1,:]
1×3 Matrix{Int64}:
 1  2  3

So the correct way to construct c is

julia> c = [a[1:1,:]; a[1:1,:]]
2×3 Matrix{Int64}:
 1  2  3
 1  2  3

as noted in one of the other answers. Using the ' operator to transpose a[1,:] is not correct because ' is actually the adjoint operation (complex tranpose). It "works" for real matrices but not for complex:

julia> a[1,:]'
1×3 adjoint(::Vector{Int64}) with eltype Int64:
 1  2  3

julia> a = [1+1im 2+2im 3+3im; 4+4im 5+5im 6+6im; 7+7im 8+8im 9+9im]
3×3 Matrix{Complex{Int64}}:
 1+1im  2+2im  3+3im
 4+4im  5+5im  6+6im
 7+7im  8+8im  9+9im

julia> a[1,:]'
1×3 adjoint(::Vector{Complex{Int64}}) with eltype Complex{Int64}:
 1-1im  2-2im  3-3im

julia> a[1:1,:]
1×3 Matrix{Complex{Int64}}:
 1+1im  2+2im  3+3im

Upvotes: 0

Andrej Oskin
Andrej Oskin

Reputation: 2332

In addition to the range index, you can transpose vectors

julia> [a[1, :]'; a[1, :]']
2×3 Array{Int64,2}:
 1  2  3
 1  2  3

It looks likes this approach is somewhat more performant, than the range index, but it should be tested on larger matrices, also it is not consistent, if you have ranges and single columns

using BenchmarkTools

f1(a) = [a[1:1,:]; a[1:1,:]]
f2(a) = [a[1, :]'; a[1, :]']

julia> @btime f1($a)
  122.440 ns (3 allocations: 352 bytes)
2×3 Array{Int64,2}:
 1  2  3
 1  2  3

julia> @btime f2($a)
  107.480 ns (3 allocations: 352 bytes)
2×3 Array{Int64,2}:
 1  2  3
 1  2  3

Upvotes: 1

Related Questions