Make data vectors, calculate lambda, and put together dataframe with all necessary data.
The census period; an index from 1 to 39 of how many years of data have been collected.
census <- 1:39
The year: 1959 to 1997 (Dennis et al use 1959-1987)
year.t <- 1959:1997
Population size is recorded as the number of females with …
females.N <- c(44,47,46,44,46,
45,46,40,39,39,
42,39,41,40,33,
36,34,39,35,34,
38,36,37,41,39,
51,47,57,48,60,
65,74,69,65,57,
70,81,99,99)
Population growth rate is (or can be expressed as) a ration of population sizes
females.N.1959 <- 44
females.N.1960 <- 47
Calculate the ratio of the 2 population sizes. This can be described as approximately a 6.8% increase from 1959 to 1960
lambda.59_60 <- females.N.1960/females.N.1959
Access the population sizes by using bracket notation rather than hard coding
# Access the data
females.N[2]
#> [1] 47
females.N[1]
#> [1] 44
# store in objects
females.N.1959 <- females.N[1]
females.N.1960 <- females.N[2]
# confirm the output
females.N.1960/females.N.1959
#> [1] 1.068182
Calculate lambda using bracket notation
lambda.59_60 <- females.N[2]/females.N[1]
The first year of data is 1959. What is lambda for 1958 to 1959?
females.N[1]
#> [1] 44
lambda.58_59 <- females.N[1]/females.N[ ] # this will be NA
This code is creating a vector of the first two lambda values.
females.N[2:3]
#> [1] 47 46
females.N[1:2]
#> [1] 44 47
females.N[2:3]/females.N[1:2]
#> [1] 1.0681818 0.9787234
This is similar t the previous code chunk, just using all of the data.
length(females.N)
#> [1] 39
females.N[2:39]/females.N[1:38]
#> [1] 1.0681818 0.9787234 0.9565217 1.0454545 0.9782609 1.0222222 0.8695652
#> [8] 0.9750000 1.0000000 1.0769231 0.9285714 1.0512821 0.9756098 0.8250000
#> [15] 1.0909091 0.9444444 1.1470588 0.8974359 0.9714286 1.1176471 0.9473684
#> [22] 1.0277778 1.1081081 0.9512195 1.3076923 0.9215686 1.2127660 0.8421053
#> [29] 1.2500000 1.0833333 1.1384615 0.9324324 0.9420290 0.8769231 1.2280702
#> [36] 1.1571429 1.2222222 1.0000000
This code is calculating all of the lambda values without hardcoding. The length of the vector of bear populations is stored in the variable len.
len <- length(females.N)
females.N[2:len]/females.N[1:len-1]
#> [1] 1.0681818 0.9787234 0.9565217 1.0454545 0.9782609 1.0222222 0.8695652
#> [8] 0.9750000 1.0000000 1.0769231 0.9285714 1.0512821 0.9756098 0.8250000
#> [15] 1.0909091 0.9444444 1.1470588 0.8974359 0.9714286 1.1176471 0.9473684
#> [22] 1.0277778 1.1081081 0.9512195 1.3076923 0.9215686 1.2127660 0.8421053
#> [29] 1.2500000 1.0833333 1.1384615 0.9324324 0.9420290 0.8769231 1.2280702
#> [36] 1.1571429 1.2222222 1.0000000
This code chunk is different because it does not create a variable for the length of the vector. The previous chunk of code created a variable to store the length of the vector, whereas this chunk uses length() to retrieve the length.
females.N[2:length(females.N)]/females.N[1:length(females.N)-1]
#> [1] 1.0681818 0.9787234 0.9565217 1.0454545 0.9782609 1.0222222 0.8695652
#> [8] 0.9750000 1.0000000 1.0769231 0.9285714 1.0512821 0.9756098 0.8250000
#> [15] 1.0909091 0.9444444 1.1470588 0.8974359 0.9714286 1.1176471 0.9473684
#> [22] 1.0277778 1.1081081 0.9512195 1.3076923 0.9215686 1.2127660 0.8421053
#> [29] 1.2500000 1.0833333 1.1384615 0.9324324 0.9420290 0.8769231 1.2280702
#> [36] 1.1571429 1.2222222 1.0000000
Make a short vector to play with; first 10 years
females.N[1:10]
#> [1] 44 47 46 44 46 45 46 40 39 39
females.Ntemp <- females.N[1:10]
Check - are there 10 numbers
females.Ntemp
#> [1] 44 47 46 44 46 45 46 40 39 39
Using the index -1 removes the first value from a vector.
females.Ntemp[-1]
#> [1] 47 46 44 46 45 46 40 39 39
9 lambdas can be calculated from the first 10 years of data.
females.Ntemp[2:10]/females.Ntemp[1:9]
#> [1] 1.0681818 0.9787234 0.9565217 1.0454545 0.9782609 1.0222222 0.8695652
#> [8] 0.9750000 1.0000000
“Negative indexing” allows you to drop a specific element from a vector.
Drop the the first element
females.Ntemp[-1]
#> [1] 47 46 44 46 45 46 40 39 39
Drop the second element
females.Ntemp[-2]
#> [1] 44 46 44 46 45 46 40 39 39
The tenth element can be dropped using the index -10
females.Ntemp[-10]
#> [1] 44 47 46 44 46 45 46 40 39
The last element can be accessed using length() in the index.
females.Ntemp[length(females.Ntemp)]
#> [1] 39
The last element can be dropped by negating the length.
females.Ntemp[-length(females.Ntemp)]
#> [1] 44 47 46 44 46 45 46 40 39
Calculate the first 9 lambdas.
lambda.i <- females.Ntemp[-1]/females.Ntemp[-10]
lambda.i <- females.Ntemp[-1]/females.Ntemp[-length(females.Ntemp)]
This removes the first element of females.N
This removes the last element of females.N
Calculate lambdas for all of the data
females.N[-1]
#> [1] 47 46 44 46 45 46 40 39 39 42 39 41 40 33 36 34 39 35 34 38 36 37 41 39 51
#> [26] 47 57 48 60 65 74 69 65 57 70 81 99 99
females.N[-length(females.N)]
#> [1] 44 47 46 44 46 45 46 40 39 39 42 39 41 40 33 36 34 39 35 34 38 36 37 41 39
#> [26] 51 47 57 48 60 65 74 69 65 57 70 81 99
lambda.i <- females.N[-length(females.N)]/females.N[-1]
This code chunk creates a vector of the lambda values, ending it with NA. I don’t know why the NA has been added.
lambda.i <- c(lambda.i,NA)
log() calculates the natural log of a number.
lambda_log <- log(lambda.i)
bear_N <- data.frame(census,
year.t,
females.N,
lambda.i,
lambda_log)
List 3 functions that allow you to examine this dataframe.
TASK
plot(x = year.t, y = females.N, xlab = "Year", ylab = "Population index (females + cubs)", type = "b")
Bears love to eat trash. Yellowstone closed the last garbage dump in 1970 https://www.yellowstonepark.com/things-to-do/yellowstone-bears-no-longer-get-garbage-treats
census <- 1:39
year.t <- 1959:1997
females.N <- c(44,47,46,44,46,
45,46,40,39,39,
42,39,41,40,33,
36,34,39,35,34,
38,36,37,41,39,
51,47,57,48,60,
65,74,69,65,57,
70,81,99,99)
lambda.i <- females.N[-1]/females.N[-length(females.N)]
lambda.i <- c(lambda.i,NA)
lambda_log <- log(lambda.i)
bear_N <- data.frame(census,
year.t,
females.N,
lambda.i,
lambda_log)
plot(females.N ~ year.t, data = bear_N,
type = "b",
ylab = "Population index (females + cubs)",
xlab = "Year")
abline(v = 1970)
abline(v = 1987, col = "red")
You simulate the population, take the lambda values in a “hat,” and pull them out randomly
hat_of_lambdas <- bear_N$lambda.i
# hist(bear_N$lambda.i)
NA NaN Inf -Inf NULL
is.na() tells you true/false is something NA
is.na(hat_of_lambdas)
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [37] FALSE FALSE TRUE
any(is.na(hat_of_lambdas) == TRUE)
#> [1] TRUE
Drop the NA
length(hat_of_lambdas)
#> [1] 39
hat_of_lambdas[39]
#> [1] NA
hat_of_lambdas[-39]
#> [1] 1.0681818 0.9787234 0.9565217 1.0454545 0.9782609 1.0222222 0.8695652
#> [8] 0.9750000 1.0000000 1.0769231 0.9285714 1.0512821 0.9756098 0.8250000
#> [15] 1.0909091 0.9444444 1.1470588 0.8974359 0.9714286 1.1176471 0.9473684
#> [22] 1.0277778 1.1081081 0.9512195 1.3076923 0.9215686 1.2127660 0.8421053
#> [29] 1.2500000 1.0833333 1.1384615 0.9324324 0.9420290 0.8769231 1.2280702
#> [36] 1.1571429 1.2222222 1.0000000
hat_of_lambdas[-length(hat_of_lambdas)]
#> [1] 1.0681818 0.9787234 0.9565217 1.0454545 0.9782609 1.0222222 0.8695652
#> [8] 0.9750000 1.0000000 1.0769231 0.9285714 1.0512821 0.9756098 0.8250000
#> [15] 1.0909091 0.9444444 1.1470588 0.8974359 0.9714286 1.1176471 0.9473684
#> [22] 1.0277778 1.1081081 0.9512195 1.3076923 0.9215686 1.2127660 0.8421053
#> [29] 1.2500000 1.0833333 1.1384615 0.9324324 0.9420290 0.8769231 1.2280702
#> [36] 1.1571429 1.2222222 1.0000000
# know how to do this for next test
This function drops the NA values
na.omit(hat_of_lambdas)
#> [1] 1.0681818 0.9787234 0.9565217 1.0454545 0.9782609 1.0222222 0.8695652
#> [8] 0.9750000 1.0000000 1.0769231 0.9285714 1.0512821 0.9756098 0.8250000
#> [15] 1.0909091 0.9444444 1.1470588 0.8974359 0.9714286 1.1176471 0.9473684
#> [22] 1.0277778 1.1081081 0.9512195 1.3076923 0.9215686 1.2127660 0.8421053
#> [29] 1.2500000 1.0833333 1.1384615 0.9324324 0.9420290 0.8769231 1.2280702
#> [36] 1.1571429 1.2222222 1.0000000
#> attr(,"na.action")
#> [1] 39
#> attr(,"class")
#> [1] "omit"
hat_of_lambdas <- hat_of_lambdas[-length(hat_of_lambdas)]
hist(hat_of_lambdas)
This code chunk will draw a random value from the hat and save it to an object.
# pulls a lambda value from the hat with replacement
sample(x = hat_of_lambdas, size = 1,replace = TRUE)
#> [1] 1.22807
# pull lambda from hat and save to object
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
This code chunk is looking at the first 6 and last 6 rows of the data frame as well as some other statistics.
head(bear_N)
#> census year.t females.N lambda.i lambda_log
#> 1 1 1959 44 1.0681818 0.06595797
#> 2 2 1960 47 0.9787234 -0.02150621
#> 3 3 1961 46 0.9565217 -0.04445176
#> 4 4 1962 44 1.0454545 0.04445176
#> 5 5 1963 46 0.9782609 -0.02197891
#> 6 6 1964 45 1.0222222 0.02197891
tail(bear_N)
#> census year.t females.N lambda.i lambda_log
#> 34 34 1992 65 0.8769231 -0.1313360
#> 35 35 1993 57 1.2280702 0.2054440
#> 36 36 1994 70 1.1571429 0.1459539
#> 37 37 1995 81 1.2222222 0.2006707
#> 38 38 1996 99 1.0000000 0.0000000
#> 39 39 1997 99 NA NA
summary(bear_N)
#> census year.t females.N lambda.i
#> Min. : 1.0 Min. :1959 Min. :33.00 Min. :0.8250
#> 1st Qu.:10.5 1st Qu.:1968 1st Qu.:39.00 1st Qu.:0.9452
#> Median :20.0 Median :1978 Median :44.00 Median :1.0000
#> Mean :20.0 Mean :1978 Mean :49.79 Mean :1.0281
#> 3rd Qu.:29.5 3rd Qu.:1988 3rd Qu.:57.00 3rd Qu.:1.1038
#> Max. :39.0 Max. :1997 Max. :99.00 Max. :1.3077
#> NA's :1
#> lambda_log
#> Min. :-0.19237
#> 1st Qu.:-0.05639
#> Median : 0.00000
#> Mean : 0.02134
#> 3rd Qu.: 0.09874
#> Max. : 0.26826
#> NA's :1
dim(bear_N)
#> [1] 39 5
N.1997 <- 99
This code chunk shows one round of the simulated bear population by multiplying the lambda value by the current year’s population size.
1.22807*99
#> [1] 121.5789
lambda_rand.t*N.1997
#> [1] 93.5
N.1998 <- lambda_rand.t*N.1997
Almost like Excel, only worst
This code chunk will determine the population in x years time by grabbing a random lambda value and multiplying it by the current population size. This process is repeated x times, once for each year.
# 1997 - 1998
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
N.1998 <- lambda_rand.t*N.1997
# 1998 - 1999
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
N.1999 <- lambda_rand.t*N.1998
# 1999 - 2000
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
N.2000 <- lambda_rand.t*N.1999
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
N.2001 <- lambda_rand.t*N.2000
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
N.2002 <- lambda_rand.t*N.2001
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
N.2003 <- lambda_rand.t*N.2002
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
N.2004 <- lambda_rand.t*N.2003
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
N.2005 <- lambda_rand.t*N.2004
This creates a graph of the predicted population numbers from the above code.
year <- seq(1997, 2004)
N.rand <- c(N.1998,N.1999,N.2000,N.2001,N.2002,N.2003,N.2004,N.2005)
df.rand <- data.frame(N.rand, year)
plot(N.rand ~ year, data = df.rand, type = "b")
This code chunk creates a for loop the more difficult way. The user must update the index.
# Initial conditions
N.1997 <- 99
N.initial <- 99
# Explore xlim = argument
plot(N.1997 ~ c(1997))
plot(N.1997 ~ c(1997), xlim = c(1997, 1997+50))
# xlim and ylim
plot(N.1997 ~ c(1997), xlim = c(1997, 1997+50), ylim = c(0, 550))
# for loop (the hard way)
N.current <- N.initial
# This is where the for loop would be
## you should not normally make a variable t because it is a function
### must change t manually
t <- 1
# Grab a lambda
lambda_rand.t <- sample(x = hat_of_lambdas, size = 1,replace = TRUE)
# Determine pop size
N.t <- N.current*lambda_rand.t
# Current year
year.t <- 1997+t
# Add this point to the plot
# points() updates an existing graph
points(N.t ~ year.t)
# Update N.current
N.current <- N.t
This will run an actual for loop.
# Make a plot with the starting pop size
plot(N.1997 ~ c(1997), xlim = c(1997, 1997+50), ylim = c(0, 550))
# Start at 1997s population size
N.current <- N.1997
# For loop
for(t in 1:50){
# Gets a random lamda
lambda_rand.t <- sample(x = hat_of_lambdas,
size = 1,
replace = TRUE)
# Determines the population for the next year
N.t <- N.current*lambda_rand.t
# Increments the year
year.t <- 1997+t
# Adds point to plot
points(N.t ~ year.t)
# changes the current pop size
N.current <- N.t
}
Goofy R plotting code/magic
par(mfrow = c(3,3), mar = c(1,1,1,1))
This creates a plot of a simulated population from 1997 to 2047. A for loop is used to pull a random lambda value and apply it to determine the next year’s population. A grid of plots can be created by running this code multiple times.
plot(N.1997 ~ c(1997), xlim = c(1997, 1997+50), ylim = c(0, 550))
N.current <- N.1997
for(t in 1:50){
lambda_rand.t <- sample(x = hat_of_lambdas,
size = 1,
replace = TRUE)
N.t <- N.current*lambda_rand.t
year.t <- 1997+t
points(N.t ~ year.t)
N.current <- N.t
}