Bringing it all together


By now you can:

This is a powerful toolset.

Let’s use these tools to explore the discrete time logistical population growth using R.


Discrete-time logistic population growth exercise

Population growth is a density-dependent process, meaning that as the size of a population, N, changes, so too does rate of population growth. In this case, we will look at discrete-time population growth. This means that the system changes in discrete time steps (e.g., \(t_{1} = 1, t_{2} = 2, t_{3} = 3\)) rather than continuous time. Discrete-time population growth is typically observed in species that have specific breeding seasons typically occurring once a year. Population size at one time step (\(N_{t}\)) is dependent on the population size before it \(N_{t-1}\).

We can calculate a predicted population size \(N_{t}\) at time \(t\) in the future if we are given an initial population size \(N_{0}\), a per capita population growth rate \(r\), and carrying capacity \(k\).

For today’s example, we will explore how population growth changes as we change the per capita growth rate \(r\). The per captia growth rate \(r\) is a useful value to know, when \(r = 0\), the per capita growth rate is zero, when \(r > 0\) there is an increase in per capita growth, and when \(r < 0\). However, as \(r\) increases, there reaches a point where population growth is chaotic.


1) We know that we can use R as a calculator. Let’s calculate some values using this equation!

Equation for discrete-time logistical growth

  • \(N_{t} = N_{t - 1} + r * N_{t - 1} * (1 - {N_{t - 1} / K})\)

a) Given a starting population \(N_{1}\) of 2 individuals, a per capita growth rate of \(r = 1\), and carrying capacity of \(k = 1000\), how many individuals should there be in the next generation? I’ll give you a start for how I’d start to set myself up to calculate this in R.

N_1 = ______ 
r   = ______
k   = ______

N_2 = ______

b) Now calculate the population when t = 2 (generation 2)


c) One more time! Calculate the population when t = 3.


Ok, this can be a bit tedious. What if I asked you to calculate for 100 generations? You would be here all day.

  1. Instead, let’s write a function in R that allows you to calculate the size a population given a starting population size \(N_1\), per capita growth rate \(r\), carrying capacity \(k\), and number of generations that you would like, in this case \(ngen = 100\). hint: i have just given you your arguments

I have started the function for you. Explain the code that is already there using comments, and fill in the parts that are missing in the blanks. Also refer to the example function that I have handed out.

dgrowth <- function(_______________) {
  n <- rep(NA, ngen)
  n[1] <- ninit

  for (i in 2:ngen) {
    n[i] = _______________ # calculate population size - hint eqn!
  }
  _______________ # return value
}

Woot! Take your function for a spin. Do you get the correct values? Compare the results with the values that you calculated by hand above in question 1.

## [1] 1.000 1.999
## [1] 1.000000 1.999000 3.994004
## [1] 1.000000 1.999000 3.994004 7.972056

3) Cool! This function should return the population values for each generation. Let’s make a quick plot of how population increases with time.

a) First, let’s make a data frame where we bind one column of time values with our vector/column of population size at time step t (calcuated using our handy function). This time let’s look at 100 time steps.

ngen = 100
pop_100 <- _________
time_100 <- _________
pop_df <- data.frame(_________, _________)

You should end up with something like this (I say like because I format things to be pretty for presentation!)

##           N time
## 1  1.000000    1
## 2  1.999000    2
## 3  3.994004    3
## 4  7.972056    4
## 5 15.880558    5
## 6 31.508924    6

b) Great! Time to plot! - don’t forget to load the necessary libraries!

ggplot(data = pop_df, aes(x = time_100, y = pop_100)) + 
  geom_line()


4 Awesome! Ok. Now let’s do some exploring. Let’s take advantage of our newly minted function and our recent knowledge of for loops! I mentioned at the beginning of this exercise that changing the value of \(r\) changes the rate of population growth

Let’s calculate the population growth for 100 generations, starting at a population size of 1, and carrying capacity k of 1000. But, let’s play with values of r.


a) Set your input values in preparation for an upcoming for loop! We will be calculating a set of predicted populations based on values of r from 0.7 to 3 by an increment of 0.1. (remember to look up functions you haven’t seen before!)

# Setup your data!
ninit = _______
ngen  = _______
k = _______
r_vals = seq(_______)

b) Before we begin, let’s take a detour to learn a new function that can be super handy. Sometimes you create one vector or dataframe and then want to add rows to it. Describe what is happening in the code below (add comments as notes for future you!)

pop1 <- dgrowth(r = 1, ninit = 1, k = 1000, ngen = 4)
pop_df1 <- data.frame(N = pop1, time = 1:4)

pop2 <- dgrowth(r = 2, ninit = 1, k = 1000, ngen = 4)
pop_df2 <- data.frame(N = pop2, time = 1:4)

pops_df <- rbind(pop_df1, pop_df2)

c) Ok, back to looping. Let’s start by just making a loop that calculates the populations for 100 generations using our different values of r. You can look at the example for loops

for (_______) {
  dgrowth(_______)
}

d) Now let’s store each new set of values in a data.frame called pops.

# Create a dataframe with an initial population using r = 1. This is the 
# data.frame that we will add rows to.
pops <- data.frame(r = 0.6, t = 1:ngen, N = dgrowth(r = 1, ninit = ninit, k = k, ngen = ngen))


for(________){
  N    <- ________
  popr <- data.frame(________)
  pops <- ________
}

e) Yay! Time for more plots! See if you can make this one!


f) One last bit of fun. Let’s use some dplyr to grab the last 10 rows for each group of r values.

Now let’s plot those values and see what we get!