In this lesson, we’ll learn about making & working with scalars, vectors and matrices in R.

Set up

  • Create a new repository on GitHub called eds212-comp-4a, with a ReadMe
  • Clone and create a new version-controlled R Project
  • Add a new R Markdown document
  • Open Anaconda Navigator, launch Jupyter Notebook, navigate to the Project folder you just created, & a new Jupyter Notebook there (when you save your Jupyter NB, make sure it’s saving in your R project)

Vectors

Reminder: Vectors in R

ringtail <- 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

Vectors in Python (basics)

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

Matrices

Matrices in R

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, addition and subtraction

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

Matrix multiplication

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.

Matrices in Python

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.

A Leslie Matrix example

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")

Create the projection matrix:

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

Specify an initial condition

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)

Find the populations for each life stage at t = 1 year

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

Critical thinking: does it seem like there should be an easier way to do these repeated calculations?

Yes! Keep this in mind for EDS 221 when we start with iteration (for loops)!

Another Leslie matrix example:

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.

  • Create the Leslie matrix for this population
  • Given an initial population structure of 5000 seeds, 0 juveniles, and 0 adults, project the population structure over 4 years.
# 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

End