pic
Personal
Website

2e. Arrays (Vectors and Matrices)

PhD in Economics

Introduction

So far, we've explored numeric and string variables, which can be interpreted as single-element objects. Now, we'll shift our focus to collections, defined as variables comprising multiple elements.

Julia provides several forms of collections, including:

  • Arrays (including vectors and matrices)

  • Tuples and Named Tuples

  • Dictionaries

  • Sets

Arrays represent one of the most common data structure for collections. They are formally defined as objects with type Array{T,d}, where d is the array's dimension and T is its elements' type (e.g., Int64 or Float64).

Two special types of arrays are vectors (1-dimensional arrays) and matrices (2-dimensional arrays). Specifically, the type Vector{T} is an alias for Array{T,1}, whereas Matrix{T} is an alias for Array{T,2}. Although we include a section about matrices, this is optional—our content concentrates almost exclusively on vectors, which are sufficient for explaining Julia's fundamentals.

Remark
Julia uses 1 as an array's first index. This contrasts with many other languages (e.g., Python), where 0 is used as the first index.

Vectors

Vectors in Julia are defined as column-vectors. Their elements are separated by a comma or a semicolon.

Code

x = [1, 2, 3]          #= column-vector (defined using commas or semicolons)
                           Vector{Int64} (alias for Array{Int64, 1}) =# 

x = [1; 2; 3]          # equivalent notation to define `x`

Output in REPL
julia>
x
3-element Vector{Int64}: 1 2 3
Remark
Arrays can hold elements of various types, such as numbers and strings. For example, [1, 2.5, "Hello"] is a valid vector in Julia, identifying its elements as having type Any (recall that Any encompasses all the possible types supported by Julia). While arrays mixing types can be created, they're highly discouraged for several reasons, including performance.

Accessing a Vector's Elements

Given a vector x, we can access its i-th element through the syntax x[i]. Additionally, we can access all the elements of x through the syntax x[:].

Code

x = [4, 5, 6]

Output in REPL
julia>
x[2]
5

julia>
x[:]
3-element Vector{Int64}: 4 5 6

It's also possible to access a subset of elements. The approaches to doing this are multiple, and next we'll present two basic ways to do it. The simplest method is by establishing the indices through a vector, whose syntax is x[<vector>].

Code

x = [4, 5, 6, 7, 8]

Output in REPL
julia>
x[[1,3]] # elements of 'x' with indices 1 and 3
2-element Vector{Int64}: 4 6

julia>
x[1,3] # be careful! this is the notation used for matrices, indicating 'x[row 1, column 3]'
ERROR: BoundsError: attempt to access 5-element Vector{Int64} at index [1, 3]

The second approach is by establishing the indices through a range. Ranges are denoted as <first>:<steps>:<last>, with Julia assuming increments of one if we omit <steps>. The first and last index in a range can be expressed respectively through the keywords begin and end.

Code

x = [4, 5, 6, 7, 8]

Output in REPL
julia>
x[1:2] # steps with unit increments (assumed by default)
2-element Vector{Int64}: 4 5

julia>
x[1:2:5] # steps with increments of 2 (explicitly indicated)
3-element Vector{Int64}: 4 6 8

julia>
x[begin:end] # all elements. Equivalent to 'x[:]' or 'x[1:end]'
3-element Vector{Int64}: 4 5 6 7 8

Matrices (OPTIONAL)

Matrices can be defined as collections of row- or column-vectors. If they're created through multiple row vectors, each row has to be separated by a semicolon ;. If we instead adopt multiple column vectors, their elements need to be separated by a space.

Note that row vectors are considered as special cases of matrices, with their elements separated by a space—they're matrices with multiple columns having one element.

Code

X = [1 2 ; 3 4]       #= matrix as a collection of row-vectors, separated by semicolons
                         Matrix{Int64} (alias for Array{Int64, 2})=#

X = [ [1,3] [2,4] ]   # identical to `C`, but defined through a collection of column-vectors

Y = [1 2 3]           #= row-vector (defined without commas)
                         Matrix{Int64} (alias for Array{Int64, 2}) =#

Output in REPL
julia>
X
2×2 Matrix{Int64}: 1 2 3 4

julia>
Y
1×3 Matrix{Int64}: 1 2 3

Accessing a Matrix's Elements

Given a matrix X, we can access x's element at row r and column c by X[r,c]. For the case of a row vector, we can access its i-th element by X[i]. [note] We could also use this approach for any matrix, as Julia also accepts a linear index for matrices. For instance, a 3x3 matrix accepts indices between 1 and 9. However, except that you want to iterate over all elements of a matrix, the notation X[r,c] is easier to interpret. Moreover, we can select all elements across the row r by X[r,:], and all elements of column c by X[:,c].

Code

X = [5 6 ; 7 8] # matrix

Y = [4 5 6]     # row-vector

Output in REPL
julia>
X
2×2 Matrix{Int64}: 5 6 7 8

julia>
X[2,1]
7

julia>
X[1,:]
2-element Vector{Int64}: 5 6

julia>
X[:,2]
2-element Vector{Int64}: 6 8

julia>
Y[2]
5

Accessing a subset of elements is possible through the same approaches as for vectors, now applied to either rows or columns.

Code

X = [5 6 ; 7 8]

Output in REPL
julia>
X
2×2 Matrix{Int64}: 5 6 7 8

julia>
X[[1,2],1]
2-element Vector{Int64}: 5 7

julia>
X[1:2,1]
2-element Vector{Int64}: 5 7

julia>
X[begin:end,1]
2-element Vector{Int64}: 5 7