Lecture 27 (lab 7)—February 28, 2006

What was covered?

R functions and commands demonstrated

R function options

R packages used

Overview

Fitting the model

> #obtain data
> corals<- read.table('http://www.unc.edu/courses/2006spring/ecol/145/001/data/lab7/year5coral.txt', header=TRUE, sep=',')

> model0<-glm(PREV_1~WSSTA,data=corals,family=poisson)
> summary(model0)

Call:
glm(formula = PREV_1 ~ WSSTA, family = poisson, data = corals)

Deviance Residuals:
    Min     1Q Median    3Q    Max
-17.790 -5.032 -2.329 2.510 16.088

Coefficients:
            Estimate Std. Error z value  Pr(>|z|)
(Intercept) 2.198401   0.051729   42.50   <2e-16 ***
WSSTA       0.268846   0.006051   44.43   <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: 4660.4 on 46 degrees of freedom
Residual deviance: 2716.8 on 45 degrees of freedom
AIC: 2914.9

Number of Fisher Scoring iterations: 6

Thus we see that each one unit increase in WSSTA multiplies the predicted mean prevalence by 1.3

> library(MASS)
> model1<-glm.nb(PREV_1~WSSTA,data=corals)
> summary(model1)

Call:
glm.nb(formula = PREV_1 ~ WSSTA, data = corals, init.theta = 0.521663980407755,
link = log)

Deviance Residuals:
    Min      1Q  Median     3Q    Max
-2.2950 -1.1682 -0.3903 0.2552 1.5750

Coefficients:
            Estimate Std. Error z value Pr(>|z|)
(Intercept)  2.13280    0.37132   5.744 9.26e-09 ***
WSSTA        0.28231    0.06564   4.301 1.70e-05 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for Negative Binomial(0.5217) family taken to be 1)

    Null deviance: 75.547 on 46 degrees of freedom
Residual deviance: 55.937 on 45 degrees of freedom
AIC: 413.98

Number of Fisher Scoring iterations: 1

Correlation of Coefficients:
(Intercept)
WSSTA -0.84

Theta: 0.522
Std. Err.: 0.102

2 x log-likelihood: -407.981

> model2<-glm.nb(PREV_1~WSSTA+I(WSSTA^2),data=corals)
> summary(model2)

Call:
glm.nb(formula = PREV_1 ~ WSSTA + I(WSSTA^2), data = corals,
init.theta = 0.526918648778831, link = log)

Deviance Residuals:
    Min      1Q  Median     3Q    Max
-2.3293 -1.1626 -0.4022 0.4045 1.7069

Coefficients:
            Estimate Std. Error z value Pr(>|z|)
(Intercept)  1.74721    0.53704   3.253 0.00114 **
WSSTA        0.45633    0.21039   2.169 0.03008 *
I(WSSTA^2)  -0.01400    0.01742  -0.804 0.42151
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for Negative Binomial(0.5269) family taken to be 1)

    Null deviance: 76.239 on 46 degrees of freedom
Residual deviance: 55.842 on 44 degrees of freedom
AIC: 415.39

Number of Fisher Scoring iterations: 1

Correlation of Coefficients:
          (Intercept) WSSTA
WSSTA     -0.87
I(WSSTA^2) 0.72       -0.95

Theta: 0.527
Std. Err.: 0.103

2 x log-likelihood: -407.393

Checking to see if observations are equivalent

>#sort the reefs by geographic sector
> sortedcorals<- corals[order(corals$SECTOR),]
>#obtain a list of SECTORs
> sector.list<- unique(sortedcorals$SECTOR)
>#save the current margin settings
> par("mar")->oldmar
>#allow for a wider left margin (2nd entry)
> par(mar=c(5.1,6.1,2.1,2.1))
>#change axis label orientation to horizontal
> par(las=1)
>#plot sorted cover values in order
> plot(sortedcorals$CORAL_COVE,1:47, axes=FALSE, xlab='% coral cover', ylab='')
>#add labels that identify the reefs
> axis(2, at=1:47, labels=as.character(sortedcorals$REEF_NAME), cex.axis=.5)
> axis(1)
> box()
>#add horizontal lines to separate observations
> abline(h=1:47, col='grey80', lty=4)
>#use loop to color the points by the geographic sector they occupy
> for(i in 1:6) {
   cur.dat<-sortedcorals[sortedcorals$SECTOR==sector.list[i],]
   cur.num<-(1:47)[sortedcorals$SECTOR==sector.list[i]]
   points(cur.dat$CORAL_COVE, cur.num, pch=16, col=i)
}
> legend(65,47, sector.list, col=1:6, cex=rep(.7,6), bty='n', pch=rep(16,6))
> par(mar=oldmar)
> par(las=0)

Explanation of the code used to produce the graph

> sortedcorals<-corals[order(corals$SECTOR),]

> sector.list<- unique(sortedcorals$SECTOR)
> sector.list

[1] CA CB CL SW TO WH
Levels: CA CB CL SW TO WH

> par("mar")
[1] 5.1 4.1 4.1 2.1

> par("mar")->oldmar
> par(mar=c(5.1,6.1,2.1,2.1))

> par(las=1)

> plot(sortedcorals$CORAL_COVE,1:47, axes=FALSE, xlab='% coral cover', ylab='')

> axis(2, at=1:47, labels=as.character(sortedcorals$REEF_NAME), cex.axis=.5)
> axis(1)
> box()

> abline(h=1:47, col='grey80', lty=4)

> legend(65,47, sector.list, col=1:6, cex=rep(.7,6), bty='n', pch=rep(16,6))

> par(mar=oldmar)
> par(las=0)

Dealing with observations that are not equivalent

Fig. 2  Effect of coral cover on prevalence

> plot(corals$CORAL_COVE, corals$PREV_1, xlab='% coral cover', ylab='Prevalence')

> glm.nb(PREV_1~WSSTA+log(CORAL_COVE),data=corals)->model2a
> glm.nb(PREV_1~WSSTA+offset(log(CORAL_COVE)),data=corals)->model2b
> glm.nb(PREV_1~WSSTA+CORAL_COVE,data=corals)->model2c

> coef(model2a)
(Intercept)     WSSTA log(CORAL_COVE)
  0.2173891 0.2199193       0.6603233

> AIC(model2a,model2b,model2c)
        df      AIC
model2a  4 407.4004
model2b  3 408.3810
model2c  4 403.3482

Revisiting the structural form of the model

> plot(corals$WSSTA, residuals(model2c, type='pearson'), xlab='WSSTA', ylab='Pearson residual')
> lines(lowess(residuals(model2c, type='pearson')~corals$WSSTA), col=2, lty=2)
> plot(corals$WSSTA, residuals(model2c, type='deviance'), xlab='WSSTA', ylab='Deviance residual')
> lines(lowess(residuals(model2c, type='deviance')~corals$WSSTA), col=2, lty=2)


    

Fig. 3 Model residuals (Pearson and deviance) plotted against WSSTA

Here ei is the ordinary residual for observation i, xij is the value of predictor xj for observation i, bj is the estimated regression coefficient of predictor xj, and eij is the value of the partial residual for predictor xj for observation i. These are then plotted against xj just as in Fig. 3. In our example, xj is WSSTA.

> library(car)
> cr.plots(model2c)

1: Change span = 0.5
2: WSSTA
3: CORAL_COVE

Selection: 2

1: Change span = 0.5
2: WSSTA
3: CORAL_COVE

Selection: 1
span: .4

1: Change span = 0.4
2: WSSTA
3: CORAL_COVE

Selection: 2

1: Change span = 0.4
2: WSSTA

          

Fig. 4  Component plus residual plots with different spans: span = 0.5 (left) and span = 0.4 (right)

> model3<-glm.nb(PREV_1 ~ WSSTA + CORAL_COVE + I(WSSTA^2), data = corals)
Warning messages:
1: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
2: alternation limit reached in: glm.nb(PREV_1 ~ WSSTA + CORAL_COVE + I(WSSTA^2), data = corals)

> model3<-glm.nb(PREV_1 ~ WSSTA + CORAL_COVE + I(WSSTA^2), data = corals, control=glm.control(maxit=100))
> summary(model3)

Call:
glm.nb(formula = PREV_1 ~ WSSTA + CORAL_COVE + I(WSSTA^2), data = corals,
control = glm.control(maxit = 100), init.theta = 0.767698858801052,
link = log)

Deviance Residuals:
    Min      1Q  Median     3Q    Max
-2.2579 -0.9526 -0.3898 0.1286 2.5436

Coefficients:
             Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.197456   0.569032  -0.347 0.728589
WSSTA        0.709989   0.183987   3.859 0.000114 ***
CORAL_COVE   0.050201   0.009937   5.052 4.38e-07 ***
I(WSSTA^2)  -0.047068   0.015578  -3.021 0.002516 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for Negative Binomial(0.7677) family taken to be 1)

    Null deviance: 107.104 on 46 degrees of freedom
Residual deviance:  54.713 on 43 degrees of freedom
AIC: 398.48

Number of Fisher Scoring iterations: 1

Correlation of Coefficients:
           (Intercept) WSSTA CORAL_COVE
WSSTA      -0.82
CORAL_COVE -0.58        0.23
I(WSSTA^2)  0.75       -0.95 -0.33

Theta: 0.768
Std. Err.: 0.162

2 x log-likelihood: -388.482

Additional residual analysis

qres.nbinom <- function(glm.obj)
{
# Quantile residuals for Negative Binomial glm
# GKS 22 Jun 97
#

y <- glm.obj$y
size <- glm.obj$theta
mu <- fitted(glm.obj)
p <- size/(mu + size)
a <- ifelse(y > 0, pbeta(p, size, pmax(y, 1)), 0)
b <- pbeta(p, size, y + 1)
u <- runif(n = length(y), min = a, max = b)
qnorm(u)
}

> qq.plot(residuals(model3,type='deviance'))
> qq.plot(qres.nbinom(model3))

    

Fig. 5  Normal probability plots of deviance residuals and randomized quantile residuals

Spatial autocorrelation

> wtmat<- read.table('http://www.unc.edu/courses/2006spring/ecol/145/001/data/lab7/wtmat5.txt')
> wtmat5<-as.matrix(wtmat)
> wtmat5[1:7,1:7]

     V1    V2    V3    V4        V5        V6 V7
1 0.000 0.125 0.125 0.125 0.0000000 0.0000000  0
2 0.125 0.000 0.125 0.125 0.0000000 0.0000000  0
3 0.125 0.125 0.000 0.125 0.0000000 0.0000000  0
4 0.125 0.125 0.125 0.000 0.0000000 0.0000000  0
5 0.000 0.000 0.000 0.000 0.0000000 0.1666667  0
6 0.000 0.000 0.000 0.000 0.1666667 0.0000000  0
7 0.000 0.000 0.000 0.000 0.0000000 0.0000000  0

Because of the way the weight matrix W is scaled for these data, the first term in the product is just one, so to compute Moran's I we can just calculate the ratio of quadratic forms that appear in the second term.

> #calculate 1'W1
> rep(1,47)%*%wtmat5%*%rep(1,47)
    [,1]
[1,] 47

> #calculate n
> dim(wtmat5)
[1] 47 47

The function residual.NB.MoranI

# This function carries out randomization test of Moran I for negative binomial
# regression residuals. It uses glm.nb from the MASS package
# The five arguments are: argument 1 = dataset for fitting model
#   argument 2 = name of model output from NB regression for actual data
#   argument 3 = number of simulations desired, such as 999 for 1000 observations
#   argument 4 = the name of the weight matrix containing neighborhood information
#   argument 5 = the type of residual, "deviance" or "pearson", in quotes
#   argument 6 = numeric value for seed in generating simulated data

residual.NB.MoranI
<-function(dataset,model,numsims,wtmat,restype,   
     seed=sample(1:1000000,1))
{
set.seed(seed)
#define moranI function
moranI.calc<-function(simres,wtres)
{
if (length(simres)>0)
{
simstd<- simres -mean(simres)
moranI<-t(simstd)%*% wtres %*% simstd/(t(simstd)%*% simstd)
} else moranI<-NA
moranI
}
#create matrix to hold results
moran.results<-NULL
flag<-0
i<-0
j<-0
#obtain model components
model$call->modelformula
RHS<-strsplit(as.character(modelformula[2]),'~')[[1]][2]
#this version only adds residuals if model converges
while(flag==0)
{
#generate new responses based on NB regression model
temp.y<-sapply(fitted(model),function(x) rnbinom(1,mu=x,size=model$theta))
#regress simulated data
glm.nb(as.formula(paste('temp.y', '~',RHS)),
   data=dataset,na.action=na.omit,control=glm.control(maxit=100))->simout1
#check if model converged. If no, do not add residuals.
if(simout1$converged) {
#obtain residuals and calculate Moran I
simres<-residuals(simout1,type=restype)
cur.moran<-moranI.calc(simres,wtmat)
i<-i+1
moran.results<-c(moran.results,cur.moran)
}
#next simulation
j<-j+1
#check if number of simulations requested is met
if(i==numsims) flag<-1
}
#finally add the actual values as the last row
res.actual<-residuals(model,type=restype)
last.moran<-moranI.calc(res.actual,wtmat)
moran.results<-c(moran.results,last.moran)
names(moran.results)<-c(as.character(1:numsims),"Actual")
moran.results
}

The function plot.NB.MoranI

#This function calculates p-value and plots randomization distribution
#arguments: argument 1 is the vector of simulated Moran I results
#   argument 2 is the name (in quotes) of the residual type for labeling graph
#   argument 3 should be 1 or 2 indicating a one- or two-tailed test
plot.NB.MoranI<-function(out.sims,restype,numtails=2)
{
#calculate p-value
cursim<-out.sims[!is.na(out.sims)]
actual.val<-cursim[length(cursim)]
#which tail is it in
medval<-median(cursim)
num.bigger<-ifelse(actual.val>medval,sum(cursim>=actual.val),
   sum(cursim<=actual.val))
#double one-tailed p-value for two-tailed value
p.val<-if(numtails==1) num.bigger/(length(cursim)) else
    2*num.bigger/(length(cursim))
morp<-out.sims[1:(length(out.sims)-1)]
zz<-density(morp)
plot.density(zz,main="Moran's I Residual Permutation Test",
    xlab="Reference Distribution",
    lwd=2,col=2,xlim=c(min(out.sims),max(out.sims)))
hist(morp,freq=F,add=T)
points(actual.val,0,pch=17,col=4,cex=1.5)
arrows(actual.val,0.4, actual.val,3,lwd=2,length=.09,code=1,col=4,lty=1)
tailtext<-if(numtails==1)   paste(restype, " residuals",
   ", # of simulations = ",
   prettyNum(length(cursim), big.mark=","),
   ", p = ",format.pval(p.val),' (one-tailed)',sep='') else 
   paste(restype, " residuals",", # of simulations = ",
   prettyNum(length(cursim), big.mark=","),
   ", p = ",format.pval(p.val),' (two-tailed)',sep='')
mtext(tailtext,line=0.5,side=3,cex=.8)
pretty.actual<-round(actual.val,3)
par(xpd=TRUE)
text(actual.val,3,"observed\nvalue ",col=4,cex=.8,pos=3)
par(xpd=FALSE)
}


#SAMPLE RUNS
#load MASS package
#library(MASS)
#carry out randomizations--999 translates into 1000 total observations
#test.sims<-residual.NB.MoranI(year5.disease,output.nb,999,wtmat5,"pearson",100)
# Calculate p-value and plot results. I do a one-tailed test.
#plot.NB.MoranI(test.sims,"pearson",numtails=1)

Fig. 6  Randomization distribution of Moran's I

> residual.NB.MoranI(corals, model3, 999,wtmat5, "pearson", 10)->out1
Warning messages:
1: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
2: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
3: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
4: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
5: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
6: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
7: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
8: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,

> length(out1)
[1] 1000

> plot.NB.MoranI(out1, "pearson", 1)

Fig. 7  Pearson residuals by sector

> boxplot(residuals(model3, type='pearson') ~corals$SECTOR, outline=FALSE)
> points(jitter(as.numeric( corals$SECTOR)), residuals(model3, type='pearson'), pch=16, col=2 , cex=.8)
> mtext('Pearson residuals by sector', side=3, line=.5, cex=.9)

> residual.NB.MoranI(corals, model3, 999, wtmat5, "deviance", 10)->out2
Warning messages:
1: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
2: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
3: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
4: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
5: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
6: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
7: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,
8: algorithm did not converge in: glm.fitter(x = X, y = Y, w = w, etastart = eta, offset = offset,

> length(out2)
[1] 1000
> plot.NB.MoranI(out2, "deviance", 1)
> boxplot(residuals(model3, type='deviance')~corals$SECTOR,outline=FALSE)
> points(jitter(as.numeric(corals$SECTOR)), residuals(model3, type='deviance'), pch=16, col=2 , cex=.8)
> mtext('Deviance residuals by sector', side=3, line=.5, cex=.9)

        

Fig. 8  Results for deviance residuals

Troubleshooting the randomization program

> residual.NB.MoranI(corals,model2c,999,wtmat5,"pearson",10)->out1a
Error: NA/NaN/Inf in foreign function call (arg 1)
In addition: Warning message:
step size truncated due to divergence

> out1a
Error: Object "out1a" not found

> residual.NB.MoranI(corals,model2c,500,wtmat5,"pearson",10)->out1a
Error: NA/NaN/Inf in foreign function call (arg 1)
In addition: Warning message:
step size truncated due to divergence

> out1a
Error: Object "out1a" not found

> residual.NB.MoranI(corals, model2c, 400, wtmat5,"pearson", 10)->out1a
Error: NA/NaN/Inf in foreign function call (arg 1)
In addition: Warning message:
step size truncated due to divergence

> residual.NB.MoranI(corals, model2c, 300, wtmat5, "pearson", 10)->out1a
> length(out1a)
[1] 301

> residual.NB.MoranI(corals, model2c, 699, wtmat5, "pearson", 100)->out1b
Warning messages:
1: iteration limit reached in: theta.ml(Y, mu, n, limit = control$maxit, trace = control$trace >
2: NaNs produced in: sqrt(1/i)
3: iteration limit reached in: theta.ml(Y, mu, n, limit = control$maxit, trace = control$trace >
4: NaNs produced in: sqrt(1/i)

> length(out1b)
[1] 700

> out<-c(out1a[1:300], out1b)

> plot.NB.MoranI(out, "pearson", 1)

Temporal autocorrelation (not done in class)

> library(date) #need the as.date function from this package
> ordered.disease<-corals[order(as.date(as.character(corals$DATE))),]

> as.character(ordered.disease$DATE)
 [1] "7/24/2002"  "7/26/2002"  "7/28/2002"  "7/28/2002"  "7/30/2002"  "7/31/2002"
 [7] "7/31/2002"  "8/1/2002"   "8/2/2002"   "9/5/2002"   "9/6/2002"   "9/7/2002"
[13] "9/8/2002"   "9/9/2002"   "9/10/2002"  "9/11/2002"  "9/16/2002"  "9/17/2002"
[19] "9/18/2002"  "9/19/2002"  "10/24/2002" "10/25/2002" "10/26/2002" "10/28/2002"
[25] "11/1/2002"  "11/2/2002"  "11/3/2002"  "11/5/2002"  "11/7/2002"  "11/8/2002"
[31] "11/25/2002" "11/26/2002" "11/27/2002" "11/28/2002" "11/30/2002" "12/1/2002"
[37] "12/3/2002"  "12/4/2002"  "12/5/2002"  "3/7/2003"   "3/8/2003"   "3/10/2003"
[43] "3/12/2003"  "3/15/2003"  "3/18/2003"  "3/19/2003"  "3/21/2003"

> sapply(1:10,function(i) as.date(as.character(ordered.disease$DATE))[(1+i): (dim(ordered.disease)[1])]-
as.date(as.character(ordered.disease$DATE))[1: (dim(ordered.disease)[1]-i)]) ->the.lags

> the.lags[[1]]
[1]  2 2 0 2 1 0 1 1 34 1 1 1 1 1 1 5 1 1 1 35 1 1 2 4 1 1 2 2 1 17 1 1 1 2 1 2 1 1 92
[40] 1 2 2 3 3 1 2

> the.lags[[2]]
[1]  4 2 2 3 1 1 2 35 35 2 2 2 2 2 6 6 2 2 36 36 2 3 6 5 2 3 4 3 18 18 2 2 3 3 3 3 2 93 93
[40] 3 4 5 6 4 3

> min(the.lags[[10]])
[1] 14

> table(unlist(the.lags))

 0  1  2  3  4  5  6  7  8   9  10  11  12  13  14  15  17  18  19  20  21  22  23  24  25
 2 27 28 22 18 16 14 14 14  11   9   9   6   5   4   1   1   2   2   3   2   3   5   4   5
26 27 28 29 30 31 32 34 35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51
 5  4  5  4  3  3  3  1  3   6   8   8  10   9   8   7   5   5   7   8  10   6   3   2   1
52 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 119
 2  1  2  2  2  2  4  2  3   4   4   5   3   5   4   2   3   3   1

Using the standardized version it then calculates the autocorrelation at lag l, , as shown below (Pinheiro & Bates 2000, p. 227).

Here N(l) is the number of pairs that go into calculating the correlation while N(0) is the total number of observations that are included in the numerator at some point. M refers to the various different apparent lag groupings contained in the list variable the.lags.

The function get.acf

#This function calculates the autocorrelation function for a variable
# Arguments: argument 1 is the maximum lag to use in calculating the ACF
# argument 2 is the variable to use in calculating ACF
# argument 3 is the list variable containing the true lag values

get.acf<-function(maxlag,oldei,the.lags) {
 #standardize variable
 ei<-(oldei-mean(oldei))/sd(oldei)
 #initialize variables
 N.list<-length(ei) 
 ACF.list<-1
 total.sum<-0
 total.count<-0
 
#cycle through all desired lags
 for (i in 1:maxlag) {
   all.guys<-NULL
   full.list<-NULL
  
#cycle through lag lists looking for desired lag
    for (j in 1:length(the.lags)) {
       cur.lag<-the.lags[[j]]
 
  #calculate numerator terms of Morans I
       first.ei<-ei[((1+j):(length(the.lags[[j]])+j))[the.lags[[j]]==i]]
       second.ei<-ei[(1:(length(the.lags[[j]])))[the.lags[[j]]==i]]
       cur.term<-first.ei*second.ei
       full.list<-c(full.list,cur.term)
 
   #determine which observations were used for this lag
       cur.guys<-unique(c(((1+j):(length(the.lags[[j]])+j))[the.lags[[j]]==i],
       (1:(length(the.lags[[j]])))[the.lags[[j]]==i]))
       all.guys<-unique(c(all.guys,cur.guys))
       }
    #average sum of squares of all observations used
    bottom<-sum(ei[all.guys]^2)/length(ei[all.guys])
  #average lagged sum of squares
    top<-sum(full.list)/length(full.list)
    cur.ACF<-top/bottom
    cur.N<-length(full.list)
    ACF.list<-c(ACF.list,cur.ACF)
    N.list<-c(N.list,cur.N)
    }
 out.mat<-cbind(0:maxlag,ACF.list,N.list)
 colnames(out.mat)<-c('lag','ACF','N')
 out.mat
}

Fig. 9  Autocorrelation of the response

> out.acf<-get.acf(10, ordered.disease$PREV_1, the.lags)
> out.acf

     lag         ACF  N
[1,]   0  1.00000000 47
[2,]   1  0.98290774 27
[3,]   2  0.60782175 28
[4,]   3  0.54641949 22
[5,]   4  0.35289774 18
[6,]   5  0.48385855 16
[7,]   6  0.24276398 14
[8,]   7  0.11626542 14
[9,]   8 -0.00919083 14
[10,]  9 -0.22915190 11
[11,] 10 -0.19324603  9

> plot(out.acf[,1], out.acf[,2], type='h', xlab='Lag', ylab='Autocorrelation', ylim=c(-1,1), col=4)
> abline(h=0,lty=1)
> lines(out.acf[,1], qnorm(.975)/sqrt(out.acf[,3]), lty=2, col=2)
> lines(out.acf[,1], -qnorm(.975)/sqrt(out.acf[,3]), lty=2, col=2)
> mtext('Autocorrelation of response', line=.5, side=3, font=2, cex=.9)

Fig. 10  Autocorrelation of the deviance residuals

> model3<-glm.nb(PREV_1 ~ WSSTA + CORAL_COVE + I(WSSTA^2), data = corals, control=glm.control(maxit=100))
> out.acf<-get.acf(10, residuals(model3, type='deviance'), the.lags)
> plot(out.acf[,1], out.acf[,2], type='h', xlab='Lag',ylab='Autocorrelation', ylim=c(-1,1), col=4)
> abline(h=0, lty=1)
> lines(out.acf[,1], qnorm(.975)/sqrt(out.acf[,3]), lty=2, col=2)
> lines(out.acf[,1], -qnorm(.975)/sqrt(out.acf[,3]), lty=2, col=2)
> mtext('Autocorrelation of residuals', line=.5, side=3, font=2, cex=.9)

Cited References

Course Home Page


Jack Weiss
Phone: (919) 962-5930
E-Mail: jack_weiss@unc.edu
Address: Curriculum in Ecology, Box 3275, University of North Carolina, Chapel Hill, 27516
Copyright © 2006
Last Revised--March 13, 2006
URL: http://www.unc.edu/courses/2006spring/ecol/145/001/docs/lectures/lecture27.htm