In this chapter we work with vectors and matrices. We cover the basic calculations that can be done with both. We also discuss how vectors and matrices can be manipulated.
7.1 Definitions of Vectors
A vector is a list of numbers that we can do “math” with. The numbers in the vector are indexed, so that we can access them. Note that vector indexing in Python starts with zero, not with 1. So Python counts the first element in a vector as element 0, the second as element 1, etc. We first need to import some important packages so that Python understands basic numerical procedures and definitions, like vectors and matrices and not with a list. The command np.array from the numpy package does just that.
Here are some examples. Vectors xyyear and names are assigned as follows:
import numpy as np# You can document your script files using the ``#`` symbol.# This allows you to add commentary to your codes.xv = np.array([1, 3.3333, 4.8976, 9])yv = np.array([9.233, 0.3453, 3.29999, 2.8])print("xv = {}".format(xv))print("yv = {}".format(yv))print("xv[0] = {}".format(xv[0]))print("xv[1] = {}".format(xv[1]))print("xv[2] = {}".format(xv[2]))
# You can document your script files using the ``#`` symbol.# This allows you to add commentary to your codes.xv<-c(1, 3.3333, 4.8976, 9)yv<-c(9.233, 0.3453, 3.29999, 2.8)cat("xv =", xv, "\n")cat("yv =", yv, "\n")cat("xv[1] =", xv[1], "\n")cat("xv[2] =", xv[2], "\n")cat("xv[3] =", xv[3], "\n")
Remember that Python starts numbering the elements with 0 and not 1! So if you want to access the first element in a vector x you’d need to type: xv[0].
If you would like to print the vector formatted, you need to set the format option of the numpy object as:
year = np.arange(2000,2004,1) # np.arange(from, to, stepsize)print("year= {}".format(year))
year= [2000 2001 2002 2003]
year<-seq(2000, 2003, by =1)# seq(from, to, by)cat("year =", year, "\n")
year = 2000 2001 2002 2003
If you would like to generate a certain number of elements between two boundary points you can use np.linspace(). Let us say we would like to generate some numbers between the lower bound of 2000 and the upper bound of 2003. We call this spanning a grid from 2000 to 2003 where we basically break the interval into evenly spaced sub-intervals. This is important for graphing (or plotting) mathematical functions which we do in the next chapter.
Let us say we want to span a grid with 5 gridpoints, so that the interval from 2000 to 2003 is broken in equally wide sub-intervals, we would write the following:
somev = np.linspace(2000,2003,5) # np.linspace(from, to, nr. of steps)print("somev= {}".format(somev))
somev= [2000. 2000.75 2001.5 2002.25 2003. ]
somev<-seq(2000, 2003, length.out =5)# seq(from, to, length.out)cat("somev =", somev, "\n")
somev = 2000 2001 2002 2002 2003
Remember from the previous chapter how arrays are very similar to lists and tuples. An array is basically a list of numbers, and numbers only! This means that indexing will work on an array, just as it worked on the list object. Same with slicing if you remember that from the previous chapter.
Here is again a list example. Let us define it first and then extract some objects from the list (which is itself an object – remember in Python everything is an object).
# A list of strings is simply:names_list = ["Tom", "Dick", "Harry", "Patrick"]# A tuple of strings is simply:names_tuple = ("Tom", "Dick", "Harry", "Patrick")print("names_list= {}".format(names_list))print("names_tuple= {}".format(names_tuple))print("names_list[1]= {}".format(names_list[1]))print("names_list[3]= {}".format(names_list[3]))
names_list= ['Tom', 'Dick', 'Harry', 'Patrick']
names_tuple= ('Tom', 'Dick', 'Harry', 'Patrick')
names_list[1]= Dick
names_list[3]= Patrick
# A list of strings is simply:names_list<-c("Tom", "Dick", "Harry", "Patrick")# A vector of strings is equivalent to a tuple in Pythonnames_vector<-c("Tom", "Dick", "Harry", "Patrick")cat("names_list =", names_list, "\n")cat("names_vector =", names_vector, "\n")cat("names_list[2] =", names_list[2], "\n")cat("names_list[4] =", names_list[4], "\n")
names_list = Tom Dick Harry Patrick
names_vector = Tom Dick Harry Patrick
names_list[2] = Dick
names_list[4] = Patrick
7.2 Simple Calculations with Vectors
Let us do some simple math with arrays (or vectors, which are one dimensional arrays).
As you can see, the numbers are added element-by-element and they are multiplied element-by-element.
This is different behavior from what we have seen so far from lists. Let us repeat the above example, but instead of numpy-arrays we use lists instead. We would then have:
This results in an error message. You cannot really do “math” on lists because the content of lists can be numbers, words, other weird objects and it is not guaranteed that doing math with these is possible. Hence, Python will not let you do “math” with lists. You can only do “list things” such as adding stuff to it, printing it, extracting info from it, etc.
7.3 Simple Calculations with Matrices
Matrices are “two dimensional” vectors. Think of a speadsheet with rows and columns that can only be filled with numbers. In Python we define as matrix again with the array() function. Here is a simple Matrix with 2 rows and 2 columns. We call this a 2-by-2 or \(2\times2\) matrix.
You can again see that when you add or multiply matrices, the operation is done element-by-element. This means that the number in position 0,0 (row 1, column 1) in matrix A is multiplied with the number in the same position 0,0 (row 1, column 1) in matrix B.
Python has some built in functions to help you generate often used matrices automatically, so you do not always have to type them in.
If you want to generate matrices filled with either zeros or ones of a particular size in Python you can use the following:
A vector of order \(n>0\) is a set of ordered numbers. \(a = \left[ \begin{array}{c} 4 \\ 3 \end{array} \right], \:
e_{1} = \left[ \begin{array}{c} 1 \\ 0 \\ 0 \end{array} \right], \: ...\)
These are column vectors. Row vectors are transposed column vectors, that is \(a'=[4 \: 3], \: e'_{1}=[1 \: 0 \: 0], \: ...\)
In Python vectors are formed as column vectors by default. We can simply transpose vectors using the transpose function t() as follows:
import numpy as npimport matplotlib.pyplot as pltimport math as mfrom scipy import stats as stimport time # Imports system time module to time your scriptplt.close('all') # close all open figures
library(ggplot2)# Load the ggplot2 library for plottinggraphics.off()# Close all open figures# Other libraries are automatically loaded in R when needed# There's no direct equivalent to the 'time' module in Python for timing in R.# However, you can use the 'system.time()' function to measure the execution time of expressions.# You can proceed with the rest of your R code here.
a<-c(4, 3)# column vectoraprime<-t(a)# transpose to get row vectorcat("a =", a, "\n")cat("a' =", aprime, "\n")
a = 4 3
a' = 4 3
7.4.2 Length of Vectors
A vector (at least a two dimensional one) has a convenient geometric representation. It is an arrow, where the two coordinates indicate the direction and length of this arrow. Vector \(a = \left[ \begin{array}{c} 4
\\ 3 \end{array} \right]\) points to the upper right (i.e. 4 over, 3 up). The length of a vector can be calculated using the Pythagoras theorem for the triangle. The length of vector \(a = \left[ \begin{array}{c} a_1 \\ a_2
\end{array} \right]\) where \(a_1\) and \(a_2\) are simply numbers, can be calculated as \(\|a\| = \sqrt{a_1^2 + a_2^2}.\) For our example, the vector norm for \(a = \left[ \begin{array}{c} 4 \\ 3 \end{array} \right]
\text{ is } \rightarrow \|a\| = \sqrt{4^2 + 3^2} = 5.\) In Python we can simply define a vector and calculate its norm (or length) as
Adding vectors is simple. We just add all numbers of two vectors ‘element-by-element’. So that \(a + b = \left[ \begin{array}{c} a_1 + b_1 \\
a_2+b_2 \end{array} \right].\) In Python this is done with
a = np.array([4,3])b = np.array([12,5])print("a= ", a)print("b= ", b)print("a+b=", a+b) # adding up vectors element-by-element
a= [4 3]
b= [12 5]
a+b= [16 8]
a<-c(4, 3)b<-c(12, 5)cat("a =", a, "\n")cat("b =", b, "\n")cat("a + b =", a+b, "\n")# adding up vectors element-by-element
a = 4 3
b = 12 5
a + b = 16 8
7.4.4 Multiplication of Vectors
A vector can be multiplied by a number (we call it a scalar denoted as :math:` lambda` to distinguish it from vectors and the numbers that it contains). The scalar is multiplied with all numbers of the vector. If we multiply the vector with \(\lambda > 1\) then the arrow that the vector symbolizes is becoming longer. If we multiply the vector with \(0 < \lambda < 1\) the arrow gets shorter. If we multiply the vector with a negative number \(\lambda < 0\) then the arrow changes direction. More formally this is \(\lambda * a =
\left[ \begin{array}{c} \lambda *a_1 \\ \lambda *a_2 \end{array} \right].\)
If you want to remove columns or rows you can use the take method and assign the result to a new matrix. Let’s say you would like to eliminate the second column from a matrix A.
If you want to replace matrix elements based on certain criteria you can use the criteria as a logical statement in combination with the choose method. In the next example we replace all the elements of the matrix that are larger than 90 with the number 90. We start by setting some elements of the matrix equal to 99.
A[:,0] =99# Fill first column with 99print("A = ", A)print("---------------")# Replace all elements > 90 with number 90B = (A>90).choose(A,90)print("(A>90).choose(A,90) = ", B)
A[, 1]<-99# Fill first column with 99cat("A =", A, "\n")cat("---------------\n")# Replace all elements > 90 with number 90B<-ifelse(A>90, 90, A)cat("(A > 90) * (A, 90) =", B, "\n")
If you want to run a loop “through” a matrix you can first find out the dimensions of the matrix using the shape method and then write nested loops, one for each dimension. Note the indentation of the various print statements in the next example!
A = np.array([[11,12,13,14],[21,22,23,24],[31,32,33,34]])print("A=", A)print("---------------")print(" Start loops ")print("---------------")nrRows, nrCols = A.shapefor i inrange(nrRows):print("Row {}".format(i+1))print("---------------")for j inrange(nrCols):print("The element in row {} and column {} is: {}".format(i+1, j+1, A[i,j]))print("Done with row {}".format(i+1))print("---------------")print("---------------")print(" All Done ")print("---------------")
A= [[11 12 13 14]
[21 22 23 24]
[31 32 33 34]]
---------------
Start loops
---------------
Row 1
---------------
The element in row 1 and column 1 is: 11
The element in row 1 and column 2 is: 12
The element in row 1 and column 3 is: 13
The element in row 1 and column 4 is: 14
Done with row 1
---------------
Row 2
---------------
The element in row 2 and column 1 is: 21
The element in row 2 and column 2 is: 22
The element in row 2 and column 3 is: 23
The element in row 2 and column 4 is: 24
Done with row 2
---------------
Row 3
---------------
The element in row 3 and column 1 is: 31
The element in row 3 and column 2 is: 32
The element in row 3 and column 3 is: 33
The element in row 3 and column 4 is: 34
Done with row 3
---------------
---------------
All Done
---------------
A<-matrix(c(11, 21, 31, 12, 22, 32, 13, 23, 33, 14, 24, 34), nrow =3, byrow =TRUE)cat("A =", A, "\n")cat("---------------\n")cat(" Start loops \n")cat("---------------\n")nrRows<-nrow(A)nrCols<-ncol(A)for(iin1:nrRows){cat("Row ", i, "\n")cat("---------------\n")for(jin1:nrCols){cat("The element in row ", i, " and column ", j, " is: ", A[i, j], "\n")}cat("Done with row ", i, "\n")cat("---------------\n")}cat("---------------\n")cat(" All Done \n")cat("---------------\n")
A = 11 22 33 21 32 14 31 13 24 12 23 34
---------------
Start loops
---------------
Row 1
---------------
The element in row 1 and column 1 is: 11
The element in row 1 and column 2 is: 21
The element in row 1 and column 3 is: 31
The element in row 1 and column 4 is: 12
Done with row 1
---------------
Row 2
---------------
The element in row 2 and column 1 is: 22
The element in row 2 and column 2 is: 32
The element in row 2 and column 3 is: 13
The element in row 2 and column 4 is: 23
Done with row 2
---------------
Row 3
---------------
The element in row 3 and column 1 is: 33
The element in row 3 and column 2 is: 14
The element in row 3 and column 3 is: 24
The element in row 3 and column 4 is: 34
Done with row 3
---------------
---------------
All Done
---------------
7.5.2 Transposing Matrices
Matrices are “two dimensional” vectors. In Python we define a matrix as
Transposing matrices requires again the t() command. It writes each column as row of a new matrix. So that the transpose of matrix \(A\) in the above example becomes:
If we transpose the transpose of matrix A, we get the original matrix A back.
7.5.3 Adding Matrices
When adding two matrices \(A\) and \(B\) we simply add all the elements of each matrix ‘element-by-element’. Note that the dimensions (i.e. the number of rows and columns) of the two matrices have to be identical. So if matrix \(A\) has dimension \(m \times n\), that is \(m\) rows and \(n\) columns, then matrix \(B\) needs to be of dimensions \(m
\times n\) as well.
When multiplying two matrices \(A\) and \(B\) we need to make sure that the number of columns of matrix \(A\) is equal the number of rows of matrix \(B\). So if \(A\) has dimension \(m \times n\) then \(B\) needs to have dimension \(n \times r\) since matrix multiplication implies that we form the ‘inner product’ of each row of \(A\) with each column of \(B\). This results in a new matrix of dimension \(m \times r\). Here is an example. Given matrices \(A = \left[ \begin{array}{ccc} 12 & 3 &6 \\
9 &-1 & -4 \end{array} \right] \text{ and } B = \left[ \begin{array}{cc} 7 & 8
\\ -2 &0 \\ 1 & 11 \end{array} \right]\)
the product of \(A\)\((2 \times 3)\) and \(B\) of dimension \((3 \times 2)\) is a matrix \(C\) with dimension \((2 \times 2)\):
In Python matrix multiplication is achieved using the command dot() or the @ operator. This last operator is new and will only work with Python 3.5 and newer.
A = np.array([[12,3,6],[3,-1,-4]])b = np.array([7,-2,1])C = np.dot(A,b) # matrix multiplied by vector: (m x n) x (n x 1) = (m x 1)D = A @ b # new matrix multiplication operatorprint("A=", A)print("b=", b)print("C=", C)print("D=", D)