In this lesson, we’ll learn about making & working with scalars, vectors and matrices in R.
eds212-comp-4a
, with a ReadMeringtail <- c(4.3, 8.9, 2.6, 7.1)
fox <- c(9.0, 12.5, 5.4, 10.9)
# Addition:
ringtail + fox
## [1] 13.3 21.4 8.0 18.0
# Subtraction:
fox - ringtail
## [1] 4.7 3.6 2.8 3.8
# Scalar multiplier:
100 * ringtail
## [1] 430 890 260 710
# Dot product:
ringtail %*% fox
## [,1]
## [1,] 241.38
Over in your Jupyter notebook, add a header.
In a new code chunk, import the numpy
package (it’s
already installed along with Anaconda)
import numpy as np
To make a vector, create a list (more on this in EDS 221) then convert to an array (with a single column = vector):
# First make it a list of values (we'll learn more about lists in 221)
list_1 = [1,2,3]
# Make it a vector using np.array:
vec_1 = np.array(list_1)
# Return vec_1 to check it out
vec_1
## array([1, 2, 3])
Cool! Let’s make another one so we can try some math:
list_2 = [10, 100, 1000]
vec_2 = np.array(list_2)
vec_2
## array([ 10, 100, 1000])
Now we can do some math with our two vectors (vec_1
and
vec_2
):
# Addition:
vec_1 + vec_2
# Subtraction:
## array([ 11, 102, 1003])
vec_2 - vec_1
# Scalar multiplier:
## array([ 9, 98, 997])
5 * vec_2
## array([ 50, 500, 5000])
BEWARE: If you do these operations with the original
lists, something very different will happen, since the
+
with lists appends the second list elements to the first
list. Let’s try it just for comparison:
list_1 + list_2
## [1, 2, 3, 10, 100, 1000]
For the dot product, use np.dot()
:
np.dot(vec_1, vec_2)
## 3210
A matrix contains data of a single class (usually numbers). Which means that we can think of the contents of a matrix as a single sequence of values, that are constrained (wrapped) to the specified dimensions of the matrix.
For example, let’s say we have 10 values:
# Make a sequence of values from 1 - 10
my_values <- seq(from = 1, to = 10)
# Look at it (always)
my_values
## [1] 1 2 3 4 5 6 7 8 9 10
Now, we can convert this into a matrix by letting R know how many rows these values should be “wrapped” into (the default is to populate by column…see documentation, and always look at what you’ve created):
my_matrix <- matrix(data = my_values, nrow = 2, ncol = 5, byrow = TRUE)
# Check it out!
my_matrix
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 6 7 8 9 10
Try some other variations to make a matrix from
my_values
to test it out. What happens if you don’t have
enough elements in the matrix to contain your vector? What happens if
your matrix has more elements than your vector?
For example:
matrix(data = my_values, nrow = 3, ncol = 4, byrow = TRUE)
## Warning in matrix(data = my_values, nrow = 3, ncol = 4, byrow = TRUE): data
## length [10] is not a sub-multiple or multiple of the number of rows [3]
## [,1] [,2] [,3] [,4]
## [1,] 1 2 3 4
## [2,] 5 6 7 8
## [3,] 9 10 1 2
So…always, always, always look at what you’ve created.
Scalar multiplication of a matrix is straightforward: just use the multiply operator (*):
4 * my_matrix
## [,1] [,2] [,3] [,4] [,5]
## [1,] 4 8 12 16 20
## [2,] 24 28 32 36 40
Addition/subtraction requires matrices of the same dimension. Let’s make another 2x5 matrix:
my_values_2 <- seq(from = 21, to = 30)
my_matrix_2 <- matrix(my_values_2, nrow = 2, byrow = TRUE)
# Check it out:
my_matrix_2
## [,1] [,2] [,3] [,4] [,5]
## [1,] 21 22 23 24 25
## [2,] 26 27 28 29 30
Add the two matrices:
my_matrix + my_matrix_2
## [,1] [,2] [,3] [,4] [,5]
## [1,] 22 24 26 28 30
## [2,] 32 34 36 38 40
Similarly for subtraction:
my_matrix_2 - my_matrix
## [,1] [,2] [,3] [,4] [,5]
## [1,] 20 20 20 20 20
## [2,] 20 20 20 20 20
As we saw in lecture, matrix multiplication is a bit more complicated (dot products of rows by columns become elements in the resulting matrix). Here’s a reminder:
We multiply matrices in R using the same operator as the dot product
for vectors: %*%
For example:
# Make a couple of 2x2 matrices:
cats <- matrix(data = c(0,4,3,1), nrow = 2, byrow = TRUE)
dogs <- matrix(data = c(6,-3,0,2), nrow = 2, byrow = TRUE)
# Look at them:
cats
## [,1] [,2]
## [1,] 0 4
## [2,] 3 1
dogs
## [,1] [,2]
## [1,] 6 -3
## [2,] 0 2
# Matrix multiplication:
cats %*% dogs
## [,1] [,2]
## [1,] 0 8
## [2,] 18 -7
Confirm that this is correct by doing the matrix multiplication by hand.
Create a matrix in Python using the np.matrix()
function
(NumPy). Basically, by creating lists within a list…
# Make one 2 x 2 matrix:
matrix_1 = np.matrix([[1, 9],
[6, 0]])
print(matrix_1)
# Make another 2 x 2 matrix:
## [[1 9]
## [6 0]]
matrix_2 = np.matrix([[0, 2],
[3, 10]])
print(matrix_2)
## [[ 0 2]
## [ 3 10]]
Then we can do basic addition, subtraction, and scalar multiplication just like we did with vectors:
# Matrix addition example:
matrix_1 + matrix_2
# Matrix subtraction example:
## matrix([[ 1, 11],
## [ 9, 10]])
matrix_1 - matrix_2
# Scalar multiplication example:
## matrix([[ 1, 7],
## [ 3, -10]])
6 * matrix_1
## matrix([[ 6, 54],
## [36, 0]])
For matrix multiplication, we use the matmul()
function
from NumPy:
my_matrix_mul = np.matmul(matrix_1, matrix_2)
print(my_matrix_mul)
## [[27 92]
## [ 0 12]]
Confirm this matrix multiplication is correct - check by hand.
In lecture, we considered a Leslie matrix for an insect with three life stages, that looked like this:
knitr::include_graphics("comp_session_images/insect_leslie.png")
insect_leslie <- matrix(c(0, 0, 600, 0.2, 0, 0, 0, 0.08, 0), nrow = 3, ncol = 3, byrow = TRUE)
# Check it out:
insect_leslie
## [,1] [,2] [,3]
## [1,] 0.0 0.00 600
## [2,] 0.2 0.00 0
## [3,] 0.0 0.08 0
Let’s say we start with 12000 eggs, 700 larvae, and 500 female adults. Create a vector containing those initial values:
# Insect lifestage populations (year 0)
insect_y0 <- c(12000, 700, 500)
Reminder: this means we’ll take the dot product of our projection matrix, and the lifestage populations.
# Populations at year 1:
insect_y1 <- insect_leslie %*% insect_y0
# Check it out:
insect_y1
## [,1]
## [1,] 300000
## [2,] 2400
## [3,] 56
# Populations by lifestage at year 2:
insect_y2 <- insect_leslie %*% insect_y1
insect_y2
## [,1]
## [1,] 33600
## [2,] 60000
## [3,] 192
# Populations by lifestage at year 3:
insect_y3 <- insect_leslie %*% insect_y2
insect_y3
## [,1]
## [1,] 115200
## [2,] 6720
## [3,] 4800
# Populations by lifestage at year 4:
insect_y4 <- insect_leslie %*% insect_y3
insect_y4
## [,1]
## [1,] 2880000.0
## [2,] 23040.0
## [3,] 537.6
Yes! Keep this in mind for EDS 221 when we start with iteration (for loops)!
You have collected information about a type of tree. There are three life stages: seeds (S), juvenile (J) and adult (A). Juvenile trees don’t produce seeds. Adults produce 50 seeds each year. 10% of seeds produced become seedlings, and 6% of seedlings go on to become adults. 95% of adult trees survive each year.
# Make the projection matrix
tree_rep <- matrix(c(0, 0, 50, 0.10, 0, 0, 0, 0.06, 0.95), nrow = 3, ncol = 3, byrow = TRUE)
# Check it out:
tree_rep
## [,1] [,2] [,3]
## [1,] 0.0 0.00 50.00
## [2,] 0.1 0.00 0.00
## [3,] 0.0 0.06 0.95
Make some projections:
# year 0: initial condition
tree_0 <- c(5000, 0, 0)
# year 1:
tree_1 <- tree_rep %*% tree_0
tree_1
## [,1]
## [1,] 0
## [2,] 500
## [3,] 0
# year 2:
tree_2 <- tree_rep %*% tree_1
tree_2
## [,1]
## [1,] 0
## [2,] 0
## [3,] 30
# year 3:
tree_3 <- tree_rep %*% tree_2
tree_3
## [,1]
## [1,] 1500.0
## [2,] 0.0
## [3,] 28.5
# year 4:
tree_4 <- tree_rep %*% tree_3
tree_4
## [,1]
## [1,] 1425.000
## [2,] 150.000
## [3,] 27.075