library(grid)
library(Matrix)
library(MASS)
library(nlme)
library(dotCall64)
library(fields)
## Loading required package: spam
## Spam version 2.1-1 (2017-07-02) is loaded.
## Type 'help( Spam)' or 'demo( spam)' for a short introduction
## and overview of this package.
## Help for individual functions is also obtained by adding the
## suffix '.spam' to the function name, e.g. 'help( chol.spam)'.
##
## Attaching package: 'spam'
## The following objects are masked from 'package:base':
##
## backsolve, forwardsolve
## Loading required package: maps
library(IPMpack)
library(spam)
library(maps)
## Load data
getwd()
## [1] "C:/Users/Paul/Documents/Rwork"
d <- read.csv("Appendix_A_Simple_data.csv")
## examine data
head(d)
## size sizeNext surv fec.seed fec.flower
## 1 3.09 NA 0 NA NA
## 2 2.81 NA 0 NA NA
## 3 4.46 6.07 1 15 1
## 4 1.68 NA 0 NA NA
## 5 3.99 NA 0 NA NA
## 6 4.07 NA 0 NA NA
## Make graphs of important demographic relationships.
par(mfrow=c(2,2),mar=c(4,4,2,1))
plot(d$size,jitter(d$surv),xlab="Size (t)", ylab="Survival to t+1") # jittered
plot(d$size,d$sizeNext,xlab="Size (t)",ylab="Size (t+1)")
plot(d$size,d$fec.seed,xlab="Size (t)",ylab="Seed Number")
hist(d$sizeNext[is.na(d$size)],main=,xlab="Recruit Size")
## make placeholder to store results from demographic relationships
params=data.frame(
surv.int=NA, # Intercept from logistic regression of survival
surv.slope=NA, # Slope from logistic regression of survival
growth.int=NA,
growth.slope=NA,
growth.sd=NA,
seed.int=NA,
seed.slope=NA,
recruit.size.mean=NA, # Mean recruit size
recruit.size.sd=NA, # Standard deviation of recruit size
establishment.prob=NA # Probability of establishment
# Intercept from linear regression of growth
# Slope from linear regression of growth
# Residual sd from the linear regression of growth
# Intercept from Poisson regression of seed number
# Slope from Poisson regression of seed number
)
#################################################
## Fit statistical models to demeographic relationships
##################################################
# 1. survival: logistic regression
surv.reg=glm(surv~size,data=d,family=binomial())
summary(surv.reg)
##
## Call:
## glm(formula = surv ~ size, family = binomial(), data = d)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.2275 -0.5815 0.2491 0.5597 2.0972
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -3.9646 0.4760 -8.329 <2e-16 ***
## size 1.2897 0.1338 9.642 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 488.69 on 399 degrees of freedom
## Residual deviance: 315.82 on 398 degrees of freedom
## (100 observations deleted due to missingness)
## AIC: 319.82
##
## Number of Fisher Scoring iterations: 5
params$surv.int=coefficients(surv.reg)[1]
params$surv.slope=coefficients(surv.reg)[2]
# 2. growth: linear regression
growth.reg=lm(sizeNext~size,data=d)
summary(growth.reg)
##
## Call:
## lm(formula = sizeNext ~ size, data = d)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.8037 -0.5434 0.0932 0.5741 2.6732
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.68135 0.19580 13.69 <2e-16 ***
## size 0.57922 0.03902 14.84 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.8866 on 278 degrees of freedom
## (220 observations deleted due to missingness)
## Multiple R-squared: 0.4421, Adjusted R-squared: 0.4401
## F-statistic: 220.3 on 1 and 278 DF, p-value: < 2.2e-16
params$growth.int=coefficients(growth.reg)[1]
params$growth.slope=coefficients(growth.reg)[2]
params$growth.sd=sd(resid(growth.reg))
# 3. seeds: Poisson regression
seed.reg=glm(fec.seed~size,data=d,family=poisson())
summary(seed.reg)
##
## Call:
## glm(formula = fec.seed ~ size, family = poisson(), data = d)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -6.5338 -1.8830 0.0529 1.5375 4.9690
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.33234 0.06370 20.92 <2e-16 ***
## size 0.30647 0.01164 26.34 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 2598.3 on 279 degrees of freedom
## Residual deviance: 1840.1 on 278 degrees of freedom
## (220 observations deleted due to missingness)
## AIC: 2942.2
##
## Number of Fisher Scoring iterations: 5
params$seed.int=coefficients(seed.reg)[1]
params$seed.slope=coefficients(seed.reg)[2]
# 4. size distribution of recruits
params$recruit.size.mean=mean(d$sizeNext[is.na(d$size)])
params$recruit.size.sd=sd(d$sizeNext[is.na(d$size)])
# 5. establishment probability
params$establishment.prob=sum(is.na(d$size))/sum(d$fec.seed,na.rm=TRUE)
## show how the statistical models conform to the data
par(mfrow=c(2,2))
xx=seq(0,8,by=.01) # sizes at which to evaluate predictions
plot(d$size,jitter(d$surv), xlab="Size (t)",ylab="Survival to t+1") # jittered
lines(xx,predict(surv.reg,
data.frame(size=xx),type="response"), col="red",lwd=3)
plot(d$size,d$sizeNext,xlab="Size (t)",ylab="Size (t+1)")
lines(xx,predict(growth.reg,data.frame(size=xx)),col="red",lwd=3)
plot(d$size,d$fec.seed,xlab="Size (t)",ylab="Seed Number (t)")
lines(xx,predict(seed.reg,
data.frame(size=xx),type='response'),col='red',lwd=3)
hist(d$sizeNext[is.na(d$size)],freq=FALSE,xlab="Recruit size",main='')
lines(xx,dnorm(xx,params$recruit.size.mean,
params$recruit.size.sd), col='red',lwd=3)
#######################################
## calculate demographic rates for the IPM using coefficients
## from the statistically fitted relationships
## and create the IPM Kernel
#########################################
# 1. survival probability function
s.x=function(x,params) {
u=exp(params$surv.int+params$surv.slope*x)
return(u/(1+u))
}
# 2. growth function
g.yx=function(xp,x,params) {
dnorm(xp,mean=params$growth.int+params$growth.slope*x,sd=params$growth.sd) }
# 3. reproduction function
f.yx=function(xp,x,params) {
params$establishment.prob*
dnorm(xp,mean=params$recruit.size.mean,sd=params$recruit.size.sd)*
exp(params$seed.int+params$seed.slope*x)
}
## create kernel
## create the details of the kernel matrix,
## including the size (100 x 100 matrix)
min.size=.9*min(c(d$size,d$sizeNext),na.rm=T)
max.size=1.1*max(c(d$size,d$sizeNext),na.rm=T)
n=100 # number of cells in the matrix
b=min.size+c(0:n)*(max.size-min.size)/n # boundary points
y=0.5*(b[1:n]+b[2:(n+1)]) # mesh points
h=y[2]-y[1] # step size
## Create the kernel
G=h*outer(y,y,g.yx,params=params) # growth matrix
S=s.x(y,params=params) # survival
F=h*outer(y,y,f.yx,params=params) # reproduction matrix
P=G # placeholder; redefine P on the next line
for(i in 1:n) P[,i]=G[,i]*S[i] # growth/survival matrix
K=P+F # full matrix
########################################
## Analyze the kernel
#######################################
# Lambda
(lam <- Re(eigen(K)$values[1]))
## [1] 1.013391
# Is the population likely to grow or shrink?
## Later on, we plot the following:
# Stable stage distribution
w.eigen <- Re(eigen(K)$vectors[,1])
stable.dist <- w.eigen/sum(w.eigen)
## Reproductive value
v.eigen <- Re(eigen(t(K))$vectors[,1])
repro.val <- v.eigen/v.eigen[1]
## The eigenvectors and lambda can be combined to obtain
## the sensitivity and elasticity matrices.
v.dot.w=sum(stable.dist*repro.val)*h
sens=outer(repro.val,stable.dist)/v.dot.w
elas=matrix(as.vector(sens)*as.vector(K)/lam,nrow=n)
## Plot summaries
library(fields)
par(mfrow=c(2,3),mar=c(4,5,2,2))
image.plot(y,y,t(K), xlab="Size (t)",ylab="Size (t+1)",
col=topo.colors(100), main="IPM matrix")
contour(y,y,t(K), add = TRUE, drawlabels = TRUE)
plot(y,stable.dist,xlab="Size",type="l",main="Stable size distribution")
plot(y,repro.val,xlab="Size",type="l",main="Reproductive values")
image.plot(y,y,t(elas),xlab="Size (t)",ylab="Size (t+1)",main="Elasticity")
image.plot(y,y,t(sens),xlab="Size (t)",ylab="Size (t+1)", main="Sensitivity")
####################################################
####################################################
####################################################
## EXTRA
## MOre accurately modeling Growth variability
#Size Dependent Variance in Growth
# Plot of the noise in the growth model.
plot(growth.reg$model$size,abs(resid(growth.reg)),
xlab='size', ylab='|residual|')
# in this regression we assume that the variation around the regression line
# increases exponentially with size.
growth.reg=gls(sizeNext~size, weights=varExp(),
na.action=na.omit, data=d)
summary(growth.reg)
## Generalized least squares fit by REML
## Model: sizeNext ~ size
## Data: d
## AIC BIC logLik
## 711.298 725.8085 -351.649
##
## Variance function:
## Structure: Exponential of variance covariate
## Formula: ~fitted(.)
## Parameter estimates:
## expon
## 0.2935594
##
## Coefficients:
## Value Std.Error t-value p-value
## (Intercept) 2.3280286 0.14227273 16.36314 0
## size 0.6585909 0.03301602 19.94762 0
##
## Correlation:
## (Intr)
## size -0.945
##
## Standardized residuals:
## Min Q1 Med Q3 Max
## -3.29676784 -0.68003669 0.07382739 0.69180794 3.35550523
##
## Residual standard error: 0.1664024
## Degrees of freedom: 280 total; 278 residual
plot(d$size,d$sizeNext, main='Growth/Shrinkage/Stasis')
lines(xx,predict(growth.reg, data.frame(size=xx)),col='red',lwd=3)
# (B) Modify the params data frame (where we store all the coefficients
# used to build the IPM) to have coefficients called growth.sd.int and
# growth.sd.slope and set the values of those coefficients equal to the
# appropriate coefficients from part (A).
params$growth.int=coefficients(growth.reg)[1]
params$growth.slope=coefficients(growth.reg)[2]
params$growth.sigma2=summary(growth.reg)$sigma^2
params$growth.sigma2.exp=as.numeric(growth.reg$modelStruct$varStruct)
#(C) Modify the growth function, g.xy(), to allow the standard deviation
# argument, sd, to be a function of size. This will follow a similar
# pattern to the argument for mean. It's probably easiest to redefine
# the function g.yx() so it works with code above to create IPMs.
g.yx=function(xp,x,params) {
dnorm(xp,mean=params$growth.int+params$growth.slope*x,
sd=sqrt(params$growth.sigma2*exp(2*params$growth.sigma2.exp*x)))
}
# (D) Rerun the code from sections 1.4.4 and 1.4.5 to obtain ??,
# sensitivities, elasticities, etc.
G=h*outer(y,y,g.yx,params=params) # growth matrix
S=s.x(y,params=params) # survival
P = G # placeholder
for(i in 1:n) P[,i]=G[,i]*S[i] # growth/survival matrix
F=h*outer(y,y,f.yx,params=params) # reproduction matrix
K=P+F # full matrix
(lam=Re(eigen(K)$values[1])) # new population growth rate
## [1] 0.980247
w.eigen=Re(eigen(K)$vectors[,1])
stable.dist=w.eigen/sum(w.eigen)
v.eigen=Re(eigen(t(K))$vectors[,1])
repro.val=v.eigen/v.eigen[1]
v.dot.w=sum(stable.dist*repro.val)*h
sens=outer(repro.val,stable.dist)/v.dot.w
elas=matrix(as.vector(sens)*as.vector(K)/lam,nrow=n)
par(mfrow=c(2,3),mar=c(4,5,2,2))
image.plot(y,y,t(K), xlab="Size (t)",ylab="Size (t+1)",
col=topo.colors(100), main="IPM matrix")
contour(y,y,t(K), add = TRUE, drawlabels = TRUE)
plot(y,stable.dist,xlab="Size",type="l",main="Stable size distribution")
plot(y,repro.val,xlab="Size",type="l",main="Reproductive values")
image.plot(y,y,t(elas),xlab="Size (t)",ylab="Size (t+1)",main="Elasticity")
image.plot(y,y,t(sens),xlab="Size (t)",ylab="Size (t+1)", main="Sensitivity")
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.
When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
summary(cars)
## speed dist
## Min. : 4.0 Min. : 2.00
## 1st Qu.:12.0 1st Qu.: 26.00
## Median :15.0 Median : 36.00
## Mean :15.4 Mean : 42.98
## 3rd Qu.:19.0 3rd Qu.: 56.00
## Max. :25.0 Max. :120.00
You can also embed plots, for example:
Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.