1-Column matrix vs. Vector

Here is a real world example:

a = Float64[-159.5; -158.5; -39.5;;]
typeof(a)
Matrix{Float64} (alias for Array{Float64, 2})
size(a)
(3, 1)
b = vec(a)
b = Float64[-159.5, -158.5, -39.5]
typeof(b)
Vector{Float64} (alias for Array{Float64, 1})
size(b)
(3, )

It seems that Julia considers them to be different? The size of a is (3,1) and the size of b is (3,). Can anyone please explain What is causing all of this to happen? Why doesn’t Julia treat them the same?

a = [1; 2; 3]
b = [1, 2, 3]
println(typeof(a))
println(typeof(b))
println(a == b)

shows

Vector{Int64}
Vector{Int64}
true

I’m confused.

2 Likes

Sorry for the confusion. Maybe that’s not a good example. Note I have modified the original post.

In my cases, when it is not working, below is often the type:
typeof(a) = Matrix{Float64}

After I do an b =vec(a), it will work and now its type is as below:
typeof(b) = Vector{Float64}

Here is a real world example:

a = Float64[-159.5; -158.5; -39.5;;]
typeof(a)
Matrix{Float64} (alias for Array{Float64, 2})

b = vec(a)
b = Float64[-159.5, -158.5, -39.5]
typeof(b)
Vector{Float64} (alias for Array{Float64, 1})

1 Like

For two dimensions we have

a1 = [[1, 2], [3, 4]]
println(typeof(a1))
b1 = [[1, 2]; [3, 4]]
println(typeof(b1))

a2 = hcat([1, 2], [3, 4])
println(typeof(a2))

b2 = vcat([1, 2], [3, 4])
println(typeof(b2))
println(b2 == b1)

with

Vector{Vector{Int64}}
Vector{Int64}
Matrix{Int64}
Vector{Int64}
true

I tend to prefer the cat-family of functions.

1 Like

I found this text which probably provides the detailed motivation for the difference between one-column matrices and vectors:

https://github.com/toivoh/Julia-Design-Thoughts/wiki/Row-vectors#motivation

5 Likes

We would need a rather hypothetical type system to equate n x 1 matrices with column and 1 x m matrices with row vectors. So compromises have to be made, probably.

Many thanks for the very helpful replies!

BTW, how can I create a size(3, 1) matrix in Julia?

I just tried. Either , or ; will result in a vector with the size of (3,) directly.

b1 = [1; 2; 3] 
b2 = [1, 2, 3]

If I created m by n matrix called B first and do b = B[:,1], it will give me a vector as well.

I saw it in your code:

julia> b1 = [1; 2; 3;;]
3×1 Matrix{Int64}:
 1
 2
 3
2 Likes

Many thanks!

Wow, I thought the double semicolons at the end were by accident. They were actually intentional.

Yeah… I tried to follow some GitHub issues on the original design of these, but they are pretty technical. What’s clear is that everyone involved had clear knowledge on what Matlab does, and they agreed that having that distinction is a good thing. I’ve seen also a C. Elrod post demonstrating that some compiler optimizations are easier with vectors (vs. Matrices that happen to have one column), particularly for simd.

In Matlab even a scalar is a Matrix with one row and one column. In Julia this would be very bad, since scalars are immutable types, and matrices are heap allocated. Probably something like that, yet more subtle, is related to the choice of having true vectors.

Some sources: (Row)Vector equality with Matrices · Issue #21998 · JuliaLang/julia · GitHub

3 Likes

Unfortunately, this design has been a major problem to my programs.

If having data in vector is so important, what harm will it do to design their programs by first converting any applicable 1-column matrix into a vector internally?

“Elrod post demonstrating that some compiler optimizations are easier with vectors (vs. Matrices that happen to have one column), particularly for simd.”

1 Like

I cannot argue in any direction about the design decision. But maybe if you show how your program reaches these problems, you can get some advice on how to structure the code to avoid them.

For instance, where are these 1-column matrices coming from? (since matrix*vector multiplications in Julia return vectors, I usually never get these).

6 Likes

I feel your frustration. OTOH is there any documentation about MATLAB’s type system (if that is what we are talking about)? I have no idea how such type identities should generalize.

1 Like

Note that this notation is valid in 1.7. In 1.6 it produces a vector:

julia> b1 = [1; 2; 3;;]
3-element Vector{Int64}:
 1
 2
 3

julia> reshape(b1,3,1)
3×1 Matrix{Int64}:
 1
 2
 3

that can be reshaped to a (3,1) matrix. (I wander why that new notation in 1.7 was not considered a breaking change, if it didn’t error before)

4 Likes

Thanks!

In a lot of my cases, the data were from a 3rd party and the function I use was from a 3rd party Julia package. Therefore, I did not really have a lot of control, except for trying to wrap up all 1-column data with vec(), or waiting till errors were reported.

1 Like

Was it one specific package? If so, part of the answer might be to make a PR to change the library to return Vectors if that would be more appropriate.

1 Like

I wrote a long post explaining many motivations for distinguishing these as types when you brought it up previously:

18 Likes

I’ve vented my frustrations with Matlab’s lack of a proper vector type several times. The post I link below is one of the posts.

In short, I use Matlab most of the time, and the fact that it does not make that distinction is one of the worst qualities of Matlab. Having a proper vector type is a huge improvement, and that’s nothing to do with performance.

7 Likes

I think Jiahao Chen’s talk at JuliaCon 2017 on “Taking Vector Transposes Seriously” is worth watching for anyone interested in this question:

6 Likes

I want to emphasize this. You should almost always be using Vectors in your code, rather than column vectors. That’s a MATLAB habit that you need to shake. I don’t think I’ve ever encountered a Julia package that uses or returns column vectors. If there is such a package, I would be interested in hearing about it.

In my opinion, the usage of the Vector type makes a lot of sense mathematically. Keep in mind that vectors in \mathbb{R}^n are actually n-tuples. They are not column vectors. A column vector is one possible matrix representation of a vector. It’s nice that Julia has different types that represent tensors of different orders. We have Number for 0-order tensors, Vector for 1st-order tensors, Matrix for 2nd-order tensors, Array{T,3} where T for 3rd-order tensors, etc.

8 Likes