chapter4 {MQMF} | R Documentation |
chapter4 The 47 R-code chunks from Model Parameter Estimation
Description
chapter4 is not an active function but rather acts as a repository for the various example code chunks found in chapter4. There are 47 r-code chunks in chapter3.
Usage
chapter4(verbose = TRUE)
Arguments
verbose |
Should instructions to written to the console, default=TRUE |
Examples
## Not run:
# All the example code from # Model Parameter Estimation
# Model Parameter Estimation
## Introduction
### Optimization
## Criteria of Best Fit
## Model Fitting in R
### Model Requirements
### A Length-at-Age Example
### Alternative Models of Growth
## Sum of Squared Residual Deviations
### Assumptions of Least-Squares
### Numerical Solutions
# R-chunk 1 Page 75
#setup optimization using growth and ssq
#convert equations 4.4 to 4.6 into vectorized R functions
#These will over-write the same functions in the MQMF package
data(LatA) # try ?LatA assumes library(MQMF) already run
vB <- function(p, ages) return(p[1]*(1-exp(-p[2]*(ages-p[3]))))
Gz <- function(p, ages) return(p[1]*exp(-p[2]*exp(p[3]*ages)))
mm <- function(p, ages) return((p[1]*ages)/(p[2] + ages^p[3]))
#specific function to calc ssq. The ssq within MQMF is more
ssq <- function(p,funk,agedata,observed) { #general and is
predval <- funk(p,agedata) #not limited to p and agedata
return(sum((observed - predval)^2,na.rm=TRUE))
} #end of ssq
# guess starting values for Linf, K, and t0, names not needed
pars <- c("Linf"=27.0,"K"=0.15,"t0"=-2.0) #ssq should=1478.449
ssq(p=pars, funk=vB, agedata=LatA$age, observed=LatA$length)
# try misspelling LatA$Length with a capital. What happens?
### Passing Functions as Arguments to other Functions
# R-chunk 2 Page 76
# Illustrates use of names within function arguments
vB <- function(p,ages) return(p[1]*(1-exp(-p[2] *(ages-p[3]))))
ssq <- function(funk,observed,...) { # only define ssq arguments
predval <- funk(...) # funks arguments are implicit
return(sum((observed - predval)^2,na.rm=TRUE))
} # end of ssq
pars <- c("Linf"=27.0,"K"=0.15,"t0"=-2.0) # ssq should = 1478.449
ssq(p=pars, funk=vB, ages=LatA$age, observed=LatA$length) #if no
ssq(vB,LatA$length,pars,LatA$age) # name order is now vital!
# R-chunk 3 Page 77
# Illustrate a problem with calling a function in a function
# LatA$age is typed as LatA$Age but no error, and result = 0
ssq(funk=vB, observed=LatA$length, p=pars, ages=LatA$Age) # !!!
### Fitting the Models
# R-chunk 4 Page 77
#plot the LatA data set Figure 4.2
oldpar <- parset() # parset and getmax are two MQMF functions
ymax <- getmax(LatA$length) # simplifies use of base graphics. For
# full colour, with the rgb as set-up below, there must be >= 5 obs
plot(LatA$age,LatA$length,type="p",pch=16,cex=1.2,xlab="Age Years",
ylab="Length cm",col=rgb(1,0,0,1/5),ylim=c(0,ymax),yaxs="i",
xlim=c(0,44),panel.first=grid())
par(oldpar) # this line not in book
# R-chunk 5 Pages 78 - 79
# use nlm to fit 3 growth curves to LatA, only p and funk change
ages <- 1:max(LatA$age) # used in comparisons
pars <- c(27.0,0.15,-2.0) # von Bertalanffy
bestvB <- nlm(f=ssq,funk=vB,observed=LatA$length,p=pars,
ages=LatA$age,typsize=magnitude(pars))
outfit(bestvB,backtran=FALSE,title="vB"); cat("\n")
pars <- c(26.0,0.7,-0.5) # Gompertz
bestGz <- nlm(f=ssq,funk=Gz,observed=LatA$length,p=pars,
ages=LatA$age,typsize=magnitude(pars))
outfit(bestGz,backtran=FALSE,title="Gz"); cat("\n")
pars <- c(26.2,1.0,1.0) # Michaelis-Menton - first start point
bestMM1 <- nlm(f=ssq,funk=mm,observed=LatA$length,p=pars,
ages=LatA$age,typsize=magnitude(pars))
outfit(bestMM1,backtran=FALSE,title="MM"); cat("\n")
pars <- c(23.0,1.0,1.0) # Michaelis-Menton - second start point
bestMM2 <- nlm(f=ssq,funk=mm,observed=LatA$length,p=pars,
ages=LatA$age,typsize=magnitude(pars))
outfit(bestMM2,backtran=FALSE,title="MM2"); cat("\n")
# R-chunk 6 Page 81
#The use of args() and formals()
args(nlm) # formals(nlm) uses more screen space. Try yourself.
# R-chunk 7 Page 81, code not in the book
#replacement for args(nlm) to keep within page borders without truncation
{cat("function (f, p, ..., hessian = FALSE, typsize = rep(1,\n")
cat(" length(p)),fscale = 1, print.level = 0, ndigit = 12, \n")
cat(" gradtol = 1e-06, stepmax = max(1000 * \n")
cat(" sqrt(sum((p/typsize)^2)), 1000), steptol = 1e-06, \n")
cat(" iterlim = 100, check.analyticals = TRUE)\n")}
# R-chunk 8 Pages 81 - 82
#Female length-at-age + 3 growth fitted curves Figure 4.3
predvB <- vB(bestvB$estimate,ages) #get optimumpredicted lengths
predGz <- Gz(bestGz$estimate,ages) # using the outputs
predmm <- mm(bestMM2$estimate,ages) #from the nlm analysis above
ymax <- getmax(LatA$length) #try ?getmax or getmax [no brackets]
xmax <- getmax(LatA$age) #there is also a getmin, not used here
oldpar <- parset(font=7) #or use parsyn() to prompt for par syntax
plot(LatA$age,LatA$length,type="p",pch=16, col=rgb(1,0,0,1/5),
cex=1.2,xlim=c(0,xmax),ylim=c(0,ymax),yaxs="i",xlab="Age",
ylab="Length (cm)",panel.first=grid())
lines(ages,predvB,lwd=2,col=4) # vB col=4=blue
lines(ages,predGz,lwd=2,col=1,lty=2) # Gompertz 1=black
lines(ages,predmm,lwd=2,col=3,lty=3) # MM 3=green
#notice the legend function and its syntax.
legend("bottomright",cex=1.2,c("von Bertalanffy","Gompertz",
"Michaelis-Menton"),col=c(4,1,3),lty=c(1,2,3),lwd=3,bty="n")
par(oldpar) # this line not in book
### Objective Model Selection
### The Influence of Residual Error Choice on Model Fit
# R-chunk 9 Page 84 - 85
# von Bertalanffy
pars <- c(27.25,0.15,-3.0)
bestvBN <- nlm(f=ssq,funk=vB,observed=LatA$length,p=pars,
ages=LatA$age,typsize=magnitude(pars),iterlim=1000)
outfit(bestvBN,backtran=FALSE,title="Normal errors"); cat("\n")
# modify ssq to account for log-normal errors in ssqL
ssqL <- function(funk,observed,...) {
predval <- funk(...)
return(sum((log(observed) - log(predval))^2,na.rm=TRUE))
} # end of ssqL
bestvBLN <- nlm(f=ssqL,funk=vB,observed=LatA$length,p=pars,
ages=LatA$age,typsize=magnitude(pars),iterlim=1000)
outfit(bestvBLN,backtran=FALSE,title="Log-Normal errors")
# R-chunk 10 Pages 85 - 86
# Now plot the resultibng two curves and the data Fig 4.4
predvBN <- vB(bestvBN$estimate,ages)
predvBLN <- vB(bestvBLN$estimate,ages)
ymax <- getmax(LatA$length)
xmax <- getmax(LatA$age)
oldpar <- parset()
plot(LatA$age,LatA$length,type="p",pch=16, col=rgb(1,0,0,1/5),
cex=1.2,xlim=c(0,xmax),ylim=c(0,ymax),yaxs="i",xlab="Age",
ylab="Length (cm)",panel.first=grid())
lines(ages,predvBN,lwd=2,col=4,lty=2) # add Normal dashed
lines(ages,predvBLN,lwd=2,col=1) # add Log-Normal solid
legend("bottomright",c("Normal Errors","Log-Normal Errors"),
col=c(4,1),lty=c(2,1),lwd=3,bty="n",cex=1.2)
par(oldpar)
### Remarks on Initial Model Fitting
## Maximum Likelihood
### Introductory Examples
# R-chunk 11 Page 88
# Illustrate Normal random likelihoods. see Table 4.1
set.seed(12345) # make the use of random numbers repeatable
x <- rnorm(10,mean=5.0,sd=1.0) # pseudo-randomly generate 10
avx <- mean(x) # normally distributed values
sdx <- sd(x) # estimate the mean and stdev of the sample
L1 <- dnorm(x,mean=5.0,sd=1.0) # obtain likelihoods, L1, L2 for
L2 <- dnorm(x,mean=avx,sd=sdx) # each data point for both sets
result <- cbind(x,L1,L2,"L2gtL1"=(L2>L1)) # which is larger?
result <- rbind(result,c(NA,prod(L1),prod(L2),1)) # result+totals
rownames(result) <- c(1:10,"product")
colnames(result) <- c("x","original","estimated","est > orig")
# R-chunk 12 page 88, Table 4.1, code not shown in book.
#tabulate results of Normal Likelihoods
kable(result,digits=c(4,8,8,0),row.names = TRUE, caption='(ref:tab401)')
# R-chunk 13 Page 89
# some examples of pnorm, dnorm, and qnorm, all mean = 0
cat("x = 0.0 Likelihood =",dnorm(0.0,mean=0,sd=1),"\n")
cat("x = 1.95996395 Likelihood =",dnorm(1.95996395,mean=0,sd=1),"\n")
cat("x =-1.95996395 Likelihood =",dnorm(-1.95996395,mean=0,sd=1),"\n")
# 0.5 = half cumulative distribution
cat("x = 0.0 cdf = ",pnorm(0,mean=0,sd=1),"\n")
cat("x = 0.6744899 cdf = ",pnorm(0.6744899,mean=0,sd=1),"\n")
cat("x = 0.75 Quantile =",qnorm(0.75),"\n") # reverse pnorm
cat("x = 1.95996395 cdf = ",pnorm(1.95996395,mean=0,sd=1),"\n")
cat("x =-1.95996395 cdf = ",pnorm(-1.95996395,mean=0,sd=1),"\n")
cat("x = 0.975 Quantile =",qnorm(0.975),"\n") # expect ~1.96
# try x <- seq(-5,5,0.2); round(dnorm(x,mean=0.0,sd=1.0),5)
## Likelihoods from the Normal Distribution
# R-chunk 14 Page 90
# Density plot and cumulative distribution for Normal Fig 4.5
x <- seq(-5,5,0.1) # a sequence of values around a mean of 0.0
NL <- dnorm(x,mean=0,sd=1.0) # normal likelihoods for each X
CD <- pnorm(x,mean=0,sd=1.0) # cumulative density vs X
oldp <- plot1(x,CD,xlab="x = StDev from Mean",ylab="Likelihood and CDF")
lines(x,NL,lwd=3,col=2,lty=3) # dashed line as these are points
abline(h=0.5,col=4,lwd=1)
par(oldp)
# R-chunk 15 Pages 91 - 92
#function facilitates exploring different polygons Fig 4.6
plotpoly <- function(mid,delta,av=5.0,stdev=1.0) {
neg <- mid-delta; pos <- mid+delta
pdval <- dnorm(c(mid,neg,pos),mean=av,sd=stdev)
polygon(c(neg,neg,mid,neg),c(pdval[2],pdval[1],pdval[1],
pdval[2]),col=rgb(0.25,0.25,0.25,0.5))
polygon(c(pos,pos,mid,pos),c(pdval[1],pdval[3],pdval[1],
pdval[1]),col=rgb(0,1,0,0.5))
polygon(c(mid,neg,neg,mid,mid),
c(0,0,pdval[1],pdval[1],0),lwd=2,lty=1,border=2)
polygon(c(mid,pos,pos,mid,mid),
c(0,0,pdval[1],pdval[1],0),lwd=2,lty=1,border=2)
text(3.395,0.025,paste0("~",round((2*(delta*pdval[1])),7)),
cex=1.1,pos=4)
return(2*(delta*pdval[1])) # approx probability, see below
} # end of plotpoly, a temporary function to enable flexibility
#This code can be re-run with different values for delta
x <- seq(3.4,3.6,0.05) # where under the normal curve to examine
pd <- dnorm(x,mean=5.0,sd=1.0) #prob density for each X value
mid <- mean(x)
delta <- 0.05 # how wide either side of the sample mean to go?
oldpar <- parset() #pre-defined MQMF base graphics set-up for par
ymax <- getmax(pd) # find maximum y value for the plot
plot(x,pd,type="l",xlab="Variable x",ylab="Probability Density",
ylim=c(0,ymax),yaxs="i",lwd=2,panel.first=grid())
approxprob <- plotpoly(mid,delta) #use function defined above
par(oldpar) # this line not in the book
### Equivalence with Sum-of-Squares
### Fitting a Model to Data using Normal Likelihoods
# R-chunk 16 Page 94
#plot of length-at-age data Fig 4.7
data(LatA) # load the redfish data set into memory and plot it
ages <- LatA$age; lengths <- LatA$length
oldpar <- plot1(ages,lengths,xlab="Age",ylab="Length",type="p",cex=0.8,
pch=16,col=rgb(1,0,0,1/5))
par(oldpar)
# R-chunk 17 Page 95
# Fit the vB growth curve using maximum likelihood
pars <- c(Linf=27.0,K=0.15,t0=-3.0,sigma=2.5) # starting values
# note, estimate for sigma is required for maximum likelihood
ansvB <- nlm(f=negNLL,p=pars,funk=vB,observed=lengths,ages=ages,
typsize=magnitude(pars))
outfit(ansvB,backtran=FALSE,title="vB by minimum -veLL")
# R-chunk 18 Page 96
#Now fit the Michaelis-Menton curve
pars <- c(a=23.0,b=1.0,c=1.0,sigma=3.0) # Michaelis-Menton
ansMM <- nlm(f=negNLL,p=pars,funk=mm,observed=lengths,ages=ages,
typsize=magnitude(pars))
outfit(ansMM,backtran=FALSE,title="MM by minimum -veLL")
# R-chunk 19 Page 96
#plot optimum solutions for vB and mm. Fig 4.8
Age <- 1:max(ages) # used in comparisons
predvB <- vB(ansvB$estimate,Age) #optimum solution
predMM <- mm(ansMM$estimate,Age) #optimum solution
oldpar <- parset() # plot the deata points first
plot(ages,lengths,xlab="Age",ylab="Length",type="p",pch=16,
ylim=c(10,33),panel.first=grid(),col=rgb(1,0,0,1/3))
lines(Age,predvB,lwd=2,col=4) # then add the growth curves
lines(Age,predMM,lwd=2,col=1,lty=2)
legend("bottomright",c("von Bertalanffy","Michaelis-Menton"),
col=c(4,1),lwd=3,bty="n",cex=1.2,lty=c(1,2))
par(oldpar)
# R-chunk 20 Pages 96 - 97
# residual plot for vB curve Fig 4.9
predvB <- vB(ansvB$estimate,ages) # predicted values for age data
resids <- lengths - predvB # calculate vB residuals
oldpar <- plot1(ages,resids,type="p",col=rgb(1,0,0,1/3),
xlim=c(0,43),pch=16,xlab="Ages Years",ylab="Residuals")
abline(h=0.0,col=1,lty=2) # emphasize the zero line
par(oldpar)
## Log-Normal Likelihoods
### Simplification of Log-Normal Likelihoods
### Log-Normal Properties
# R-chunk 21 Page 100
# meanlog and sdlog affects on mode and spread of lognormal Fig 4.10
x <- seq(0.05,5.0,0.01) # values must be greater than 0.0
y <- dlnorm(x,meanlog=0,sdlog=1.2,log=FALSE) #dlnorm=likelihoods
y2 <- dlnorm(x,meanlog=0,sdlog=1.0,log=FALSE)#from log-normal
y3 <- dlnorm(x,meanlog=0,sdlog=0.6,log=FALSE)#distribution
y4 <- dlnorm(x,0.75,0.6) #log=TRUE = log-likelihoods
oldpar <- parset(plots=c(1,2)) #MQMF base plot formatting function
plot(x,y3,type="l",lwd=2,panel.first=grid(),
ylab="Log-Normal Likelihood")
lines(x,y,lwd=2,col=2,lty=2)
lines(x,y2,lwd=2,col=3,lty=3)
lines(x,y4,lwd=2,col=4,lty=4)
legend("topright",c("meanlog sdlog"," 0.0 0.6 0.0",
" 1.0"," 0.0 1.2"," 0.75 0.6"),
col=c(0,1,3,2,4),lwd=3,bty="n",cex=1.0,lty=c(0,1,3,2,4))
plot(log(x),y3,type="l",lwd=2,panel.first=grid(),ylab="")
lines(log(x),y,lwd=2,col=2,lty=2)
lines(log(x),y2,lwd=2,col=3,lty=3)
lines(log(x),y4,lwd=2,col=4,lty=4)
par(oldpar) # return par to old settings; this line not in book
# R-chunk 22 Pages 100 - 101
set.seed(12354) # plot random log-normal numbers as Fig 4.11
meanL <- 0.7; sdL <- 0.5 # generate 5000 random log-normal
x <- rlnorm(5000,meanlog = meanL,sdlog = sdL) # values
oldpar <- parset(plots=c(1,2)) # simplifies plots par() definition
hist(x[x < 8.0],breaks=seq(0,8,0.25),col=0,main="")
meanx <- mean(log(x)); sdx <- sd(log(x))
outstat <- c(exp(meanx-(sdx^2)),exp(meanx),exp(meanx+(sdx^2)/2))
abline(v=outstat,col=c(4,1,2),lwd=3,lty=c(1,2,3))
legend("topright",c("mode","median","bias-correct"),
col=c(4,1,2),lwd=3,bty="n",cex=1.2,lty=c(1,2,3))
outh <- hist(log(x),breaks=30,col=0,main="") # approxnormal
hans <- addnorm(outh,log(x)) #MQMF function; try ?addnorm
lines(hans$x,hans$y,lwd=3,col=1) # type addnorm into the console
par(oldpar) # return par to old settings; this line not in book
# R-chunk 23 Page 101
#examine log-normal propoerties. It is a bad idea to reuse
set.seed(12345) #'random' seeds, use getseed() for suggestions
meanL <- 0.7; sdL <- 0.5 #5000 random log-normal values then
x <- rlnorm(5000,meanlog = meanL,sdlog = sdL) #try with only 500
meanx <- mean(log(x)); sdx <- sd(log(x))
cat(" Original Sample \n")
cat("Mode(x) = ",exp(meanL - sdL^2),outstat[1],"\n")
cat("Median(x) = ",exp(meanL),outstat[2],"\n")
cat("Mean(x) = ",exp(meanL + (sdL^2)/2),outstat[3],"\n")
cat("Mean(log(x) = 0.7 ",meanx,"\n")
cat("sd(log(x) = 0.5 ",sdx,"\n")
### Fitting a Curve using Log-Normal Likelihoods
# R-chunk 24 Page 103
# fit a Beverton-Holt recruitment curve to tigers data Table 4.2
data(tigers) # use the tiger prawn data set
lbh <- function(p,biom) return(log((p[1]*biom)/(p[2] + biom)))
#note we are returning the log of Beverton-Holt recruitment
pars <- c("a"=25,"b"=4.5,"sigma"=0.4) # includes a sigma
best <- nlm(negNLL,pars,funk=lbh,observed=log(tigers$Recruit),
biom=tigers$Spawn,typsize=magnitude(pars))
outfit(best,backtran=FALSE,title="Beverton-Holt Recruitment")
predR <- exp(lbh(best$estimate,tigers$Spawn))
#note exp(lbh(...)) is the median because no bias adjustment
result <- cbind(tigers,predR,tigers$Recruit/predR)
# R-chunk 25 Page 103
# Fig 4.12 visual examination of the fit to the tigers data
oldp <- plot1(tigers$Spawn,predR,xlab="Spawning Biomass","Recruitment",
maxy=getmax(c(predR,tigers$Recruit)),lwd=2)
points(tigers$Spawn,tigers$Recruit,pch=16,cex=1.1,col=2)
par(oldp) # return par to old settings; this line not in book
# R-chunk 26 page 104, Table 4.12, code not shown in book.
#tabulating observed, predicted and residual recruitment
colnames(result) <- c("SpawnB","Recruit","PredR","Residual")
kable(result,digits=c(1,1,3,4), caption='(ref:tab402)')
### Fitting a Dynamic Model using Log-Normal Errors
# R-chunk 27 Page 106
data(abdat) # plot abdat fishery data using a MQMF helper Fig 4.13
plotspmdat(abdat) # function to quickly plot catch and cpue
# R-chunk 28 Pages 106 - 107
# Use log-transformed parameters for increased stability when
# fitting the surplus production model to the abdat data-set
param <- log(c(r= 0.42,K=9400,Binit=3400,sigma=0.05))
obslog <- log(abdat$cpue) #input log-transformed observed data
bestmod <- nlm(f=negLL,p=param,funk=simpspm,indat=as.matrix(abdat),
logobs=obslog) # no typsize, or iterlim needed
#backtransform estimates, outfit's default, as log-transformed
outfit(bestmod,backtran = TRUE,title="abdat") # in param
# R-chunk 29 Pages 107 - 108
# Fig 4.14 Examine fit of predicted to data
predce <- simpspm(bestmod$estimate,abdat) #compare obs vs pred
ymax <- getmax(c(predce,obslog))
oldp <- plot1(abdat$year,obslog,type="p",maxy=ymax,ylab="Log(CPUE)",
xlab="Year",cex=0.9)
lines(abdat$year,predce,lwd=2,col=2)
par(oldp) # return par to old settings; this line not in book
## Likelihoods from the Binomial Distribution
### An Example using Binomial Likelihoods
# R-chunk 30 Page 109
#Use Binomial distribution to test biased sex-ratio Fig 4.15
n <- 60 # a sample of 60 animals
p <- 0.5 # assume a sex-ration of 1:1
m <- 1:60 # how likely is each of the 60 possibilites?
binom <- dbinom(m,n,p) # get individual likelihoods
cumbin <- pbinom(m,n,p) # get cumulative distribution
oldp <- plot1(m,binom,type="h",xlab="Number of Males",ylab="Probability")
abline(v=which.closest(0.025,cumbin),col=2,lwd=2) # lower 95% CI
par(oldp) # return par to old settings; this line not in book
# R-chunk 31 Page 111
# plot relative likelihood of different p values Fig 4.16
n <- 60 # sample size; should really plot points as each independent
m <- 20 # number of successes = finding a male
p <- seq(0.1,0.6,0.001) #range of probability we find a male
lik <- dbinom(m,n,p) # R function for binomial likelihoods
oldp <- plot1(p,lik,type="l",xlab="Prob. of 20 Males",ylab="Prob.")
abline(v=p[which.max(lik)],col=2,lwd=2) # try "p" instead of "l"
par(oldp) # return par to old settings; this line not in book
# R-chunk 32 Page 111
# find best estimate using optimize to finely search an interval
n <- 60; m <- 20 # trials and successes
p <- c(0.1,0.6) #range of probability we find a male
optimize(function(p) {dbinom(m,n,p)},interval=p,maximum=TRUE)
### Open Bay Juvenile Fur Seal Population Size
# R-chunk 33 Page 112
# Juvenile furseal data-set Greaves, 1992. Table 4.3
furseal <- c(32,222,1020,704,1337,161.53,31,181,859,593,1125,
135.72,29,185,936,634,1238,153.99)
columns <- c("tagged(m)","Sample(n)","Population(X)",
"95%Lower","95%Upper","StErr")
furs <- matrix(furseal,nrow=3,ncol=6,dimnames=list(NULL,columns),
byrow=TRUE)
#tabulate fur seal data Table 4.3
kable(furs, caption='(ref:tab403)')
# R-chunk 34 Pages 113 - 114
# analyse two pup counts 32 from 222, and 31 from 181, rows 1-2 in
# Table 4.3. Now set-up storage for solutions
optsol <- matrix(0,nrow=2,ncol=2,
dimnames=list(furs[1:2,2],c("p","Likelihood")))
X <- seq(525,1850,1) # range of potential population sizes
p <- 151/X #range of proportion tagged; 151 originally tagged
m <- furs[1,1] + 1 #tags observed, with Bailey's adjustment
n <- furs[1,2] + 1 # sample size with Bailey's adjustment
lik1 <- dbinom(m,n,p) # individaul likelihoods
#find best estimate with optimize to finely search an interval
#use unlist to convert the output list into a vector
#Note use of Bailey's adjustment (m+1), (n+1) Caughley, (1977)
optsol[1,] <- unlist(optimize(function(p) {dbinom(m,n,p)},p,
maximum=TRUE))
m <- furs[2,1]+1; n <- furs[2,2]+1 #repeat for sample2
lik2 <- dbinom(m,n,p)
totlik <- lik1 * lik2 #Joint likelihood of 2 vectors
optsol[2,] <- unlist(optimize(function(p) {dbinom(m,n,p)},p,
maximum=TRUE))
# R-chunk 35 Page 114
# Compare outcome for 2 independent seal estimates Fig 4.17
# Should plot points not a line as each are independent
oldp <- plot1(X,lik1,type="l",xlab="Total Pup Numbers",
ylab="Probability",maxy=0.085,lwd=2)
abline(v=X[which.max(lik1)],col=1,lwd=1)
lines(X,lik2,lwd=2,col=2,lty=3) # add line to plot
abline(v=X[which.max(lik2)],col=2,lwd=1) # add optimum
#given p = 151/X, then X = 151/p and p = optimum proportion
legend("topright",legend=round((151/optsol[,"p"])),col=c(1,2),lwd=3,
bty="n",cex=1.1,lty=c(1,3))
par(oldp) # return par to old settings; this line not in book
### Using Multiple Independent Samples
# R-chunk 36 Pages 114 - 115
#Combined likelihood from 2 independent samples Fig 4.18
totlik <- totlik/sum(totlik) # rescale so the total sums to one
cumlik <- cumsum(totlik) #approx cumulative likelihood for CI
oldp <- plot1(X,totlik,type="l",lwd=2,xlab="Total Pup Numbers",
ylab="Posterior Joint Probability")
percs <- c(X[which.closest(0.025,cumlik)],X[which.max(totlik)],
X[which.closest(0.975,cumlik)])
abline(v=percs,lwd=c(1,2,1),col=c(2,1,2))
legend("topright",legend=percs,lwd=c(2,4,2),bty="n",col=c(2,1,2),
cex=1.2) # now compare with averaged count
m <- furs[3,1]; n <- furs[3,2] # likelihoods for the
lik3 <- dbinom(m,n,p) # average of six samples
lik4 <- lik3/sum(lik3) # rescale for comparison with totlik
lines(X,lik4,lwd=2,col=3,lty=2) #add 6 sample average to plot
par(oldp) # return par to old settings; this line not in book
### Analytical Approaches
## Other Distributions
## Likelihoods from the Multinomial Distribution
### Using the Multinomial Distribution
# R-chunk 37 Page 119
#plot counts x shell-length of 2 cohorts Figure 4.19
cw <- 2 # 2 mm size classes, of which mids are the centers
mids <- seq(8,54,cw) #each size class = 2 mm as in 7-9, 9-11, ...
obs <- c(0,0,6,12,35,40,29,23,13,7,10,14,11,16,11,11,9,8,5,2,0,0,0,0)
# data from (Helidoniotis and Haddon, 2012)
dat <- as.matrix(cbind(mids,obs)) #xy matrix needed by inthist
oldp <- parset() #set up par declaration then use an MQMF function
inthist(dat,col=2,border=3,width=1.8, #histogram of integers
xlabel="Shell Length mm",ylabel="Frequency",xmin=7,xmax=55)
par(oldp) # return par to old settings; this line not in book
# R-chunk 38 Page 121
#cohort data with 2 guess-timated normal curves Fig 4.20
oldp <- parset() # set up the required par declaration
inthist(dat,col=0,border=8,width=1.8,xlabel="Shell Length mm",
ylabel="Frequency",xmin=7,xmax=55,lwd=2) # MQMF function
#Guess normal parameters and plot those curves on histogram
av <- c(18.0,34.5) # the initial trial and error means and
stdev <- c(2.75,5.75) # their standard deviations
prop1 <- 0.55 # proportion of observations in cohort 1
n <- sum(obs) #262 observations, now calculate expected counts
cohort1 <- (n*prop1*cw)*dnorm(mids,av[1],stdev[1]) # for each
cohort2 <- (n*(1-prop1)*cw)*dnorm(mids,av[2],stdev[2])# cohort
#(n*prop1*cw) scales likelihoods to suit the 2mm class width
lines(mids,cohort1,lwd=2,col=1)
lines(mids,cohort2,lwd=2,col=4)
par(oldp) # return par to old settings; this line not in book
# R-chunk 39 Page 122
#wrapper function for calculating the multinomial log-likelihoods
#using predfreq and mnnegLL, Use ? and examine their code
wrapper <- function(pars,obs,sizecl,midval=TRUE) {
freqf <- predfreq(pars,sum(obs),sizecl=sizecl,midval=midval)
return(mnnegLL(obs,freqf))
} # end of wrapper which uses MQMF::predfreq and MQMF::mnnegLL
mids <- seq(8,54,2) # each size class = 2 mm as in 7-9, 9-11, ...
av <- c(18.0,34.5) # the trial and error means and
stdev <- c(2.95,5.75) # standard deviations
phi1 <- 0.55 # proportion of observations in cohort 1
pars <-c(av,stdev,phi1) # combine parameters into a vector
wrapper(pars,obs=obs,sizecl=mids) # calculate total -veLL
# R-chunk 40 Page 122
# First use the midpoints
bestmod <- nlm(f=wrapper,p=pars,obs=obs,sizecl=mids,midval=TRUE,
typsize=magnitude(pars))
outfit(bestmod,backtran=FALSE,title="Using Midpts"); cat("\n")
#Now use the size class bounds and cumulative distribution
#more sensitive to starting values, so use best pars from midpoints
X <- seq((mids[1]-cw/2),(tail(mids,1)+cw/2),cw)
bestmodb <- nlm(f=wrapper,p=bestmod$estimate,obs=obs,sizecl=X,
midval=FALSE,typsize=magnitude(pars))
outfit(bestmodb,backtran=FALSE,title="Using size-class bounds")
# R-chunk 41 Page 123
#prepare the predicted Normal distribution curves
pars <- bestmod$estimate # best estimate using mid-points
cohort1 <- (n*pars[5]*cw)*dnorm(mids,pars[1],pars[3])
cohort2 <- (n*(1-pars[5])*cw)*dnorm(mids,pars[2],pars[4])
parsb <- bestmodb$estimate # best estimate with bounds
nedge <- length(mids) + 1 # one extra estimate
cump1 <- (n*pars[5])*pnorm(X,pars[1],pars[3])#no need to rescale
cohort1b <- (cump1[2:nedge] - cump1[1:(nedge-1)])
cump2 <- (n*(1-pars[5]))*pnorm(X,pars[2],pars[4]) # cohort 2
cohort2b <- (cump2[2:nedge] - cump2[1:(nedge-1)])
# R-chunk 42 Page 123
#plot the alternate model fits to cohorts Fig 4.21
oldp <- parset() #set up required par declaration; then plot curves
pick <- which(mids < 28)
inthist(dat[pick,],col=0,border=8,width=1.8,xmin=5,xmax=28,
xlabel="Shell Length mm",ylabel="Frequency",lwd=3)
lines(mids,cohort1,lwd=3,col=1,lty=2) # have used setpalette("R4")
lines(mids,cohort1b,lwd=2,col=4) # add the bounded results
label <- c("midpoints","bounds") # very minor differences
legend("topleft",legend=label,lwd=3,col=c(1,4),bty="n",
cex=1.2,lty=c(2,1))
par(oldp) # return par to old settings; this line not in book
# R-chunk 43 Page 124
# setup table of results for comparison of fitting strategies
predmid <- rowSums(cbind(cohort1,cohort2))
predbnd <- rowSums(cbind(cohort1b,cohort2b))
result <- as.matrix(cbind(mids,obs,predmid,predbnd,predbnd-predmid))
colnames(result) <- c("mids","Obs","Predmid","Predbnd","Difference")
result <- rbind(result,c(NA,colSums(result,na.rm=TRUE)[2:5]))
# R-chunk 44 page 125, Table 4.4, code not shown in book.
#tabulate the results of fitting cohort data in two ways
kable(result,digits=c(0,0,4,4,4),align=c("r","r","r","r","r"))
## Likelihoods from the Gamma Distribution
# R-chunk 45 Pages 126 - 127
#Illustrate different Gamma function curves Figure 4.22
X <- seq(0.0,10,0.1) #now try different shapes and scale values
dg <- dgamma(X,shape=1,scale=1)
oldp <- plot1(X,dg,xlab = "Quantile","Probability Density")
lines(X,dgamma(X,shape=1.5,scale=1),lwd=2,col=2,lty=2)
lines(X,dgamma(X,shape=2,scale=1),lwd=2,col=3,lty=3)
lines(X,dgamma(X,shape=4,scale=1),lwd=2,col=4,lty=4)
legend("topright",legend=c("Shape 1","Shape 1.5","Shape 2",
"Shape 4"),lwd=3,col=c(1,2,3,4),bty="n",cex=1.25,lty=1:4)
mtext("Scale c = 1",side=3,outer=FALSE,line=-1.1,cex=1.0,font=7)
par(oldp) # return par to old settings; this line not in book
## Likelihoods from the Beta Distribution
# R-chunk 46 Pages 127 - 128
#Illustrate different Beta function curves. Figure 4.23
x <- seq(0, 1, length = 1000)
oldp <- parset()
plot(x,dbeta(x,shape1=3,shape2=1),type="l",lwd=2,ylim=c(0,4),
yaxs="i",panel.first=grid(), xlab="Variable 0 - 1",
ylab="Beta Probability Density - Scale1 = 3")
bval <- c(1.25,2,4,10)
for (i in 1:length(bval))
lines(x,dbeta(x,shape1=3,shape2=bval[i]),lwd=2,col=(i+1),lty=c(i+1))
legend(0.5,3.95,c(1.0,bval),col=c(1:7),lwd=2,bty="n",lty=1:5)
par(oldp) # return par to old settings; this line not in book
## Bayes' Theorem
### Introduction
### Bayesian Methods
### Prior Probabilities
# R-chunk 47 Pages 132 - 133
# can prior probabilities ever be uniniformative? Figure 4.24
x <- 1:1000
y <- rep(1/1000,1000)
cumy <- cumsum(y)
group <- sort(rep(c(1:50),20))
xlab <- seq(10,990,20)
oldp <- par(no.readonly=TRUE) # this line not in book
par(mfrow=c(2,1),mai=c(0.45,0.3,0.05,0.05),oma=c(0.0,1.0,0.0,0.0))
par(cex=0.75, mgp=c(1.35,0.35,0), font.axis=7,font=7,font.lab=7)
yval <- tapply(y,group,sum)
plot(x,cumy,type="p",pch=16,cex=0.5,panel.first=grid(),
xlim=c(0,1000),ylim=c(0,1),ylab="",xlab="Linear Scale")
plot(log(x),cumy,type="p",pch=16,cex=0.5,panel.first=grid(),
xlim=c(0,7),xlab="Logarithmic Scale",ylab="")
mtext("Cumulative Probability",side=2,outer=TRUE,cex=0.9,font=7)
par(oldp) # return par to old settings; this line not in book
## End(Not run)
[Package MQMF version 0.1.5 Index]