In [1]:
using Dates, Printf, DelimitedFiles
include("printmat.jl") #a function for prettier matrix printing
Out[1]:
are different things, even if they happen to "look" similar. For instance, a 1x1 array is not a scalar and an nx1 array is not a vector. This is discussed in some detail further down.
However, we first present some common features of all arrays (vectors or multi-dimensional arrays).
The typical ways of getting an array are
The next few cells give simple examples.
In [2]:
z = [11 12; #typing in your matrix
21 22]
println("A matrix that we typed in:")
printmat(z)
x = readdlm("Data/MyData.csv",',',skipstart=1) #read matrix from file
println("First four lines of x from csv file:")
printmat(x[1:4,:])
An easy way to create an array is to use the fill()
function.
A = fill(0,(10,2)) #10x2, integers (0)
B = fill(0.0,10) #vector with 10 elements, floats (0.0)
C = fill(NaN,(10,2)) #10x2, floats (NaN)
D = fill("",3) #vector with 3 elements, strings ("")
E = fill(Date(1),3) #vector with 3 elements, dates (0001-01-01)
In [3]:
x = fill(0.0,(3,2)) #creates a 3x2 matrix filled with 0.0
println("so far, x is filled with 0.0. For instance, x[1,1] is $(x[1,1])")
for i = 1:size(x,1), j = 1:size(x,2)
x[i,j] = i/j
end
println("\nx after some computations")
printmat(x)
You can also create an array by
A = Array{Int}(undef,10,2) #10x2, integers
F = Array{Any}(undef,3) #vector with 3 elements, can include anything
The undef
signals that the matrix is yet not initialized. This is more cumbersome than fill()
, but sometimes more flexible.
In [4]:
F = Array{Any}(undef,3)
F[1] = [1;2;3;4] #F[1] contains a vector
F[2] = "Sultans of Swing" #F[2] a string
F[3] = 1978 #F[3] an integer
printmat(F)
Growing a matrix is done by [A;B]
and/or [A B]
(or by vcat
, hcat
and cat
). This is somewhat slow, so do not use it for appending to a matrix in a long loop. Instead, pre-allocate the matrix and then fill it (see above).
However, growing a vector is not that slow. It can be done by
push!(old vector,new element 1,new element 2)
If you instead want to append all elements of a vector, then do
append!(old vector,vector to append)
In [5]:
A = [11 12;
21 22]
B = [1 2;
0 10]
z = [A;B] #same as vcat(A,B)
println("\n","stacking A and B vertically")
printmat(z)
z2 = [A B] #same as hcat(A,B)
println("\n","stacking A and B horizontally")
printmat(z2)
In [6]:
B = Float64[] #empty vector, to include floats
for i = 1:3
x_i = 2.0 + 10^i
push!(B,x_i) #adding an element at the end
end
println("a vector with 3 elements:")
printmat(B)
In [7]:
A = [collect(1:i) for i=1:3] #this creates a vector of vectors
println("A[1] is vector with 1 element, A[2] a vector with 2 elements,...")
printmat(A)
B = map(i->collect(1:i),1:3)
printmat(B)
The most common way to use parts of an array is by indexing. For instance, to use the second column of A, do A[:,2]
.
Notice that A[1,:]
gives a (column) vector (yes, it does), while A[1:1,:]
gives a 1xk matrix. (It looks like a row vector, but is really a matrix with just one row.)
Also notice that z = A[1,:]
creates an independent copy, so changing z
will not change A
.
In case you do not need an independent copy, then y = view(A,1,:)
creates a view of the first row of A
. This saves memory and is often faster. Notice, however, that changing y
will now change A
.
In [8]:
A = [11 12;
21 22]
println("A:")
printmat(A)
println("\nsecond column of A:")
printmat(A[:,2])
println("\n","first row of A (as a vector): ")
printmat(A[1,:]) #notice 1 makes it a vector
println("\n","first row of A: ")
printmat(A[1:1,:]) #use 1:1 to keep it as a 1x2 matrix
println("\n","view of first row of A: ")
y = view(A,1,:)
printmat(y)
In [9]:
println("A simple way...which works well when you want to create a few variables")
x1 = A[:,1]
x2 = A[:,2]
printmat(x2)
println("Another, prettier way")
(z1,z2) = [A[:,i] for i = 1:2]
printmat(z2)
Matrices, vectors and scalars are different things, even if they contain the same number of elements. In particular,
(a) an $n\times1$ matrix is not the same thing as an $n$ vector
(b) a $1\times1$ matrix or a 1-element vector are not the same thing as a scalar.
As you will see further on, vectors are often more convenient than $n\times1$ matrices.
To convert a 1-element vector or 1x1 matrix C
to a scalar, just do myScalar = C[]
.
In [10]:
A = ones(3,1) #this is a 3x1 matrix
B = ones(3) #a vector with 3 elements
println("The sizes of matrix A and vector B: $(size(A)) $(size(B))")
println("\nTesting if A==B: ",isequal(A,B))
println("\nThe nx1 matrix A and n-element vector B can often be used together, for instance, as in A+B, whose size is ",size(A+B))
printmat(A+B)
In [11]:
C = ones(1,1) #a 1x1 matrix
c = 1 #a scalar
println("\nc/C would give an error since C is a (1x1) matrix")
println("\nInstead, do c/C[]: ",c/C[])
if length(C) == 1 && !isa(C,Number)
C = C[]
end
println("\nAfter conversion of C, do c/C: ",c/C)
If $x$ is a vector and $A$ a matrix, then $x'x$ and $x'A*x$ are scalars. This is what a linear algebra text book would teach you, so vectors are very useful.
This is not true if x is an array of size $n\times1$. In that case the result is a 1x1 array.
Recommendation: use vectors (instead if $nx1$ arrays) when you can.
In [12]:
x = [1;2] #this is a vector
A = [11 12;
21 22]
println("\nx'x and x'A*x when x is a 2 element vector: ",x'x," ",x'A*x)
x = zeros(Int,2,1) #this is a 2x1 matrix (array)
x[1] = 1
x[2] = 2
println("\nx'x and x'A*x when x is a 2x1 array: ",x'x," ",x'A*x)
If x1
and x2
are two arrays, then y=[x1,x2]
is a vector (of arrays) where y[1] = x1
and y[2] = x2
. (If you instead want to stack x1
and x2
into a single matrix, use [x1 x2]
, [x1;x2]
or one of the cat
functions discussed above.)
In this case y[1]
is actually a view of x1
so changing elements of one changes the other.
In [13]:
x1 = ones(3,2)
x2 = [1;2]
y = [x1,x2] #a vector of arrays
println(size(y))
printmat(y[1])
printmat(y[2])
Vectors and matrices (arrays) can take lots of memory space, so Julia is designed to avoid unnecessary copies of arrays. In short, notice the following
B = A
creates two names of the same array (changing one changes the other)B = reshape(A,n,m)
, B = vec(A)
, and B = A'
and create another view of the same array (changing one changes the other)
In [14]:
function f1(A)
A[1] = A[1]/2 #changing ELEMENTS of A, affects outside value
#A = A/2 #this would NOT affect the outside value
return A
end
x = [1.0 2.0]
printlnPs("original x: ",x)
y1 = f1(x)
printlnPs("x after calling f1(x): ",x)
In [ ]: