-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathCountBayesAnalysis.R
More file actions
486 lines (422 loc) · 17.3 KB
/
Copy pathCountBayesAnalysis.R
File metadata and controls
486 lines (422 loc) · 17.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
#######################################################################
#######################################################################
## This script was created by Dr. Jen Cruz as part of ##
## the Applied Population Ecology Class ###
## ##
## Here we import our cleaned data for a single year of point count ##
# observations for Piute ground squirrels at the NCA and run a ##
## closed population N-mixture analysis. The model is hierarchical #
# with : (1) an ecological submodel linking abundance to #
## environmental predictors at each site; (2) an observation submodel #
## linking detection probability to relevant predictors. ##
## We rerun previous single season model from unmarked in JAGS Bayesian.##
# Abundance is expected to be higher in sites with more sagebrush #
# and lower in those with more cheatgrass. # #
# Detection may be related to observer effects and to time of day #
#######################################################################
##### Set up your workspace and load relevant packages -----------
# Clean your workspace to reset your R environment. #
rm( list = ls() )
# Check that you are in the right project folder
getwd()
# load packages:
library( tidyverse )
options( dplyr.width = Inf, dplyr.print_min = 100 )
library( jagsUI )
###################################################################
#### Load or create data -----------------------------------------
# set directory where your data are:
datadir <- paste( getwd(), "/Data/", sep = "" )
# load cleaned data
closeddf <- read.csv( file = paste( datadir, "closed_counts.csv", sep = ""),
header = TRUE )
#view
head( closeddf ); dim( closeddf )
#### End of data load -------------
####################################################################
##### Ready data for analysis --------------
# extract broad parameters of interest
#number of sites:
I <- length( closeddf$o.sites )
#number of visits
J = 3
#Create a new dataframe to scale predictors starting with site level predictors #
XI <- closeddf %>%
select( cheatgrass, sagebrush ) %>%
mutate( cheatgrass = scale( cheatgrass),
sagebrush = scale( sagebrush) )
#for sitexvisit predictor we create separate objects for each
#create index of columns of interest
tidx <- grep("time", colnames( closeddf), value = FALSE)
oidx <- grep( "obs", colnames(closeddf), value = FALSE)
#also for our observations
yidx <- grep( "count.j", colnames( closeddf ), value = FALSE)
#now use those indices to automatically select correct columns and scale
time_sc <- scale( closeddf[ ,tidx] )
#we want a quadratic term for time also
time2_sc <- scale( (closeddf[ ,tidx])^2 )
# for observers, we will include them as a random intercept instead
# of a fixed effect so we convert them to a number to represent index
obvs <- as.matrix( closeddf[,oidx] )
obvs <- as.numeric( as.factor(obvs) )
#turn back into matrix
obvs <- structure( obvs, dim = dim( closeddf[,oidx] ), class = "matrix" )
#number of observers
S <- max(obvs, na.rm = TRUE)
#For homework you need to run only one of the three model versions below
# List your choice here including some reasoning for your choice:
# Answer:
#
##########################################################################
####### m1 single season N-mixture abundance model #
# ecological predictors: cheatgrass and sagebrush #
# detection predictors: time and observer as random intercept #
############################################################################
############## Specify model in bugs language: #####################
sink( "m1.txt" )
cat( "
model{
#priors
#for detection model:
#define intercept as mean probs:
int.det <- log( mean.det / ( 1 - mean.det ) )
mean.det ~ dbeta( 4, 4 )
#random intercept for observer
for( s in 1:S ){
eps.det[s] ~ dnorm( 0, pres.det ) T(-7, 7)
}
#associated variance of random intercepts:
pres.det <- 1/ ( sigma.det * sigma.det )
#sigma prior specified as a student t half-normal:
sigma.det ~ dt( 0, 2.5, 7 ) T( 0, )
#priors for detection coefficients:
#define as a slightly informative prior
for( a in 1:A){
alpha[ a ] ~ dnorm( 0, 0.2 ) T(-7, 7 )
}
#priors for abundance coefficients:
for( b in 1:B ){
#define as a slightly informative prior
beta[ b ] ~ dnorm( 0, 0.2 ) T(-7, 7 )
}
#prior for abundance model intercept
int.lam ~ dgamma( 0.01, 0.01 ) T(-10, 10 )
# ecological model of abundance
for( i in 1:I ){
#relative abundance modelled as a Poisson distribution
N[ i ] ~ dpois( lambda[ i ] )
#linking abundance rate to predictor
log( lambda[ i ] ) <- #intercept for abundance
int.lam +
# fixed effects of sagebrush and cheatgrass
inprod( beta, XI[ i, ] )
}
#observation model
for( i in 1:I ){
for( j in 1:J ){
#model for probability of detection
logit( p[i,j] ) <- #intercept for detection
int.det +
#random intercept for observer effect
eps.det[ obvs[i,j] ] +
#quadratic effect of time of day
alpha[1] * time[i,j] +
alpha[2] * time2[i,j]
#observed counts distributed as a Binomial:
y_obs[ i, j ] ~ dbin( p[i,j], N[i] )
#Model evaluation: We calculate Chi-squared discrepancy
#start with expected abundance
eval[i,j] <- p[i,j] * N[i]
#compare vs observed counts
E[i,j] <- pow( ( y_obs[i,j] - eval[i,j] ), 2 ) /
( eval[i,j] + 0.001 )
# Generate replicate data and compute fit stats
#expected counts
y_hat[ i, j ] ~ dbin( p[i,j], N[i] )
#compare vs expected counts
E.new[i,j] <- pow( ( y_hat[i,j] - eval[i,j] ), 2 ) /
( eval[i,j] + 0.001 )
} #close J
} #close I
#derived estimates of model fit
fit <- sum( E[,] )
fit.new <- sum( E.new[,] )
} #model close
", fill = TRUE )
sink()
################ end of model specification #####################################
modelname <- "m1.txt"
#parameters monitored
params <- c( 'int.det' #intercept for detection
, 'int.lam' #intercept for lamda
, 'alpha' #detection coefficients
, 'eps.det' #random intercepts in detection
, 'sigma.det' #error for random intercept
, 'beta' #abundance coefficients
, 'p' #estimate of detection probability
, 'y_hat' #predicted observations
, 'N' #estimates of abundance
, 'fit' #estimate of fit for observed data
, 'fit.new' #estimate of fit for predicted data
)
#initial values defined as max counts
Nst <- apply( closeddf[ ,yidx], 1, max, na.rm = TRUE )
#replace 0s with 1
Nst[which(Nst== 0 )] <- 1
#how many ecological predictors that are fixed effects
B <- dim(XI)[2]
#how many detection predictors that are fixed effects
A <- 2
#define initial parameter values
inits <- function(){ list( beta = rnorm( B ),
alpha = rnorm( A ),
N = Nst ) }
#define data that will go in the model
str( win.data <- list( y_obs = as.matrix( closeddf[ ,yidx] ),
#number of sites, surveys, det predictors, and abund preds
I = I, J = J, A = A, B = B, S = S,
#site level habitat predictors
XI = XI,
#observation predictors:
time = time_sc,
time2 = time2_sc,
obvs = obvs
) )
#call JAGS and summarize posteriors:
m1 <- autojags( win.data, inits = inits, params, modelname, #
n.chains = 5, n.thin = 10, n.burnin = 20000,
iter.increment = 10000, max.iter = 500000,
Rhat.limit = 1.1,
save.all.iter = FALSE, parallel = TRUE )
#view results
m1
plot(m1)
#chat
hist( m1$sims.list$fit / m1$sims.list$fit.new )
#mean chat
mean( m1$mean$fit ) / mean( m1$mean$fit.new )
#Bayesian pvalue
plot( m1$sims.list$fit, m1$sims.list$fit.new )
###### end m1 ########
########## we add a model with random effects for site ####
##########################################################################
####### m2 single season N-mixture abundance model #
# ecological predictors: cheatgrass and sagebrush as fixed effects #
# site as random intercept to account for over-dispersion #
# detection predictors: time as fixed effect #
# observer as random intercept to account for technician differences #
############################################################################
############## Specify model in bugs language: #####################
sink( "m2.txt" )
cat( "
model{
#priors
#for detection model:
#define intercept as mean probs:
int.det <- log( mean.det / ( 1 - mean.det ) )
mean.det ~ dbeta( 4, 4 )
#random intercept for observer
for( s in 1:S ){
eps.det[s] ~ dnorm( 0, pres.det ) T(-7, 7)
}
#associated variance of random intercepts:
pres.det <- 1/ ( sigma.det * sigma.det )
#sigma prior specified as a student t half-normal:
sigma.det ~ dt( 0, 2.5, 7 ) T( 0, )
#priors for detection coefficients:
#define as a slightly informative prior
for( a in 1:A){
alpha[a] ~ dnorm( 0, 0.2 ) T(-7, 7 )
}
#priors for abundance coefficients:
for( b in 1:B ){
#define as a slightly informative prior
beta[ b ] ~ dnorm( 0, 0.2 ) T(-7, 7 )
}
#prior for abundance model intercept
int.lam ~ dunif( 0, 10 )
#random intercept for site
for( i in 1:I ){
eps.i[i] ~ dnorm( 0, pres.i ) T(-7, 7)
}
#associated variance of random intercepts:
pres.i <- 1/ ( sigma.i * sigma.i )
#sigma prior specified as a student t half-normal:
sigma.i ~ dt( 0, 2.5, 7 ) T( 0, )
# ecological model of abundance
for( i in 1:I ){
N[ i ] ~ dpois( lambda[ i ] )
log( lambda[ i ] ) <- int.lam +
inprod( beta, XI[ i, ] ) +
#random effect for site
eps.i[ i ]
#observation model
for( j in 1:J ){
logit( p[i,j] ) <- int.det +
#random intercept for observer effect
eps.det[ obvs[i,j] ] +
#fixed effects
alpha[1] * time[i,j] +
alpha[2] * time2[i,j]
#observed counts
y_obs[ i, j ] ~ dbin( p[i,j], N[i] )
#for model evaluation we calculate Chi-squared discrepancy
#expected abundance
eval[i,j] <- p[i,j] * N[i]
#compare vs observed counts
E[i,j] <- pow( ( y_obs[i,j] - eval[i,j] ), 2 ) /
( eval[i,j] + 0.001 )
# Generate replicate data and compute fit stats
#expected counts
y_hat[ i, j ] ~ dbin( p[i,j], N[i] )
E.new[i,j] <- pow( ( y_hat[i,j] - eval[i,j] ), 2 ) /
( eval[i,j] + 0.001 )
} #close J
} #close I
#derived estimate of fit
fit <- sum( E[,] )
fit.new <- sum( E.new[,] )
} #model close
", fill = TRUE )
sink()
################ end of model specification #####################################
modelname <- "m2.txt"
#parameters monitored
params <- c( 'int.det' #intercept for detection
, 'int.lam' #intercept for lamda
, 'alpha' #detection coefficients
, 'eps.det' #random intercepts in detection
, 'sigma.det' #error for random intercept
, 'beta' #abundance coefficients
, 'eps.i' #random site intercept in abundance
, 'p' #estimate of detection probability
, 'y_hat' #predicted observations
, 'N' #estimates of abundance
, 'fit' #estimate of fit for observed data
, 'fit.new' #estimate of fit for predicted data
)
#call JAGS and summarize posteriors:
m2 <- autojags( win.data, inits = inits, params, modelname, #
n.chains = 5, n.thin = 10, n.burnin = 20000,
iter.increment = 10000, max.iter = 500000,
Rhat.limit = 1.1,
save.all.iter = FALSE, parallel = TRUE )
#view
summary( m2 )
plot(m2)
#calculate chat
mean( m2$mean$fit ) / mean( m2$mean$fit.new )
#plot Bayesian p value
plot( x = m2$sims.list$fit, y = m2$sims.list$fit.new )
###### end m2 ########
##########################################################################
####### m3 single season N-mixture abundance model -ZIP #
# ecological predictors: cheatgrass and sagebrush #
# detection predictors: time and observer as random intercept #
############################################################################
############## Specify model in bugs language: #####################
sink( "m3.txt" )
cat( "
model{
#priors
#for detection model:
#define intercept as mean probs:
int.det <- log( mean.det / ( 1 - mean.det ) )
mean.det ~ dbeta( 4, 4 )
#random intercept for observer
for( s in 1:S ){
eps.det[s] ~ dnorm( 0, pres.det ) T(-7, 7)
}
#associated variance of random intercepts:
pres.det <- 1/ ( sigma.det * sigma.det )
#sigma prior specified as a student t half-normal:
sigma.det ~ dt( 0, 2.5, 7 ) T( 0, )
#priors for detection coefficients:
#define as a slightly informative prior
for( a in 1:A ){
alpha[a] ~ dnorm( 0, 0.2 ) T(-7, 7 )
}
#priors for abundance coefficients:
for( b in 1:B ){
#define as a slightly informative prior
beta[ b ] ~ dnorm( 0, 0.2 ) T(-7, 7 )
}
# site suitability prior
omega ~ dbeta( 4, 4 )
#prior for abundance model intercept
int.lam ~ dgamma( 0.01, 0.01 ) T(0, 10 )
# ecological model of abundance
for( i in 1:I ){
#latent suitability state
z[ i ] ~ dbern( omega )
#true abundance now conditional on z
N[ i ] ~ dpois( lambda[ i ] * z[ i ] )
#mean relative abundance related to ecological predictors
log( lambda[ i ] ) <- int.lam +
inprod( beta, XI[ i, ] )
#observation model
for( j in 1:J ){
#probability of detection related to predictors
logit( p[i,j] ) <- int.det +
#random intercept for observer effect
eps.det[ obvs[i,j] ] +
#fixed effects
alpha[1] * time[i,j] +
alpha[2] * time2[i,j]
#observed counts
y_obs[ i, j ] ~ dbin( p[i,j], N[i] )
#for model evaluation we calculate Chi-squared discrepancy
#expected abundance
eval[i,j] <- p[i,j] * N[i]
#compare vs observed counts
E[i,j] <- pow( ( y_obs[i,j] - eval[i,j] ), 2 ) /
( eval[i,j] + 0.5 )
# Generate replicate data and compute fit stats
#expected counts
y_hat[ i, j ] ~ dbin( p[i,j], N[i] )
E.new[i,j] <- pow( ( y_hat[i,j] - eval[i,j] ), 2 ) /
( eval[i,j] + 0.5 )
} #close J
} #close I
#derived estimate of fit
fit <- sum( E[,] )
fit.new <- sum( E.new[,] )
} #model close
", fill = TRUE )
sink()
################ end of model specification #####################################
modelname <- "m3.txt"
#parameters monitored
params <- c( 'int.det' #intercept for detection
, 'int.lam' #intercept for lamda
, 'alpha' #detection coefficients
, 'eps.det' #random intercepts in detection
, 'sigma.det' #error for random intercept
, 'omega' #suitability parameter
, 'beta' #abundance coefficients
, 'p' #estimate of detection probability
, 'y_hat' #predicted observations
, 'N' #estimates of abundance
, 'fit' #estimate of fit for observed data
, 'fit.new' #estimate of fit for predicted data
)
#call JAGS and summarize posteriors:
m3 <- autojags( win.data, inits = inits, params, modelname, #
n.chains = 5, n.thin = 10, n.burnin = 20000,
iter.increment = 10000, max.iter = 500000,
Rhat.limit = 1.1,
save.all.iter = FALSE, parallel = TRUE )
#view
summary( m3 )
plot(m3)
#calculate chat
mean( m3$mean$fit ) / mean( m3$mean$fit.new )
#plot Bayesian p value
plot( x = m3$sims.list$fit, y = m3$sims.list$fit.new )
###### end m3 ########
############################################################################
################## Save your data and workspace ###################
# Save workspace:
save.image( "CountBayesResults.RData" )
######### End of saving section ##################################
############# END OF SCRIPT #####################################