rubythinking 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/r/0_all.R ADDED
@@ -0,0 +1,4600 @@
1
+ library(rethinking)
2
+
3
+ ## R code 0.1
4
+ print( "All models are wrong, but some are useful." )
5
+
6
+ ## R code 0.2
7
+ x <- 1:2
8
+ x <- x*10
9
+ x <- log(x)
10
+ x <- sum(x)
11
+ x <- exp(x)
12
+ x
13
+
14
+ ## R code 0.3
15
+ ( log( 0.01^200 ) )
16
+ ( 200 * log(0.01) )
17
+
18
+ ## R code 0.4
19
+ # Load the data:
20
+ # car braking distances in feet paired with speeds in km/h
21
+ # see ?cars for details
22
+ data(cars)
23
+
24
+ # fit a linear regression of distance on speed
25
+ m <- lm( dist ~ speed , data=cars )
26
+
27
+ # estimated coefficients from the model
28
+ coef(m)
29
+
30
+ # plot residuals against speed
31
+ plot( resid(m) ~ speed , data=cars )
32
+
33
+ ## R code 0.5
34
+ install.packages(c("coda","mvtnorm","devtools","dagitty"))
35
+ library(devtools)
36
+ devtools::install_github("rmcelreath/rethinking")
37
+
38
+ ## R code 2.1
39
+ ways <- c( 0 , 3 , 8 , 9 , 0 )
40
+ ways/sum(ways)
41
+
42
+ ## R code 2.2
43
+ dbinom( 6 , size=9 , prob=0.5 )
44
+
45
+ ## R code 2.3
46
+ # define grid
47
+ p_grid <- seq( from=0 , to=1 , length.out=20 )
48
+
49
+ # define prior
50
+ prior <- rep( 1 , 20 )
51
+
52
+ # compute likelihood at each value in grid
53
+ likelihood <- dbinom( 6 , size=9 , prob=p_grid )
54
+
55
+ # compute product of likelihood and prior
56
+ unstd.posterior <- likelihood * prior
57
+
58
+ # standardize the posterior, so it sums to 1
59
+ posterior <- unstd.posterior / sum(unstd.posterior)
60
+
61
+ ## R code 2.4
62
+ plot( p_grid , posterior , type="b" ,
63
+ xlab="probability of water" , ylab="posterior probability" )
64
+ mtext( "20 points" )
65
+
66
+ ## R code 2.5
67
+ prior <- ifelse( p_grid < 0.5 , 0 , 1 )
68
+ prior <- exp( -5*abs( p_grid - 0.5 ) )
69
+
70
+ ## R code 2.6
71
+ library(rethinking)
72
+ globe.qa <- quap(
73
+ alist(
74
+ W ~ dbinom( W+L ,p) , # binomial likelihood
75
+ p ~ dunif(0,1) # uniform prior
76
+ ) ,
77
+ data=list(W=6,L=3) )
78
+
79
+ # display summary of quadratic approximation
80
+ precis( globe.qa )
81
+
82
+ ## R code 2.7
83
+ # analytical calculation
84
+ W <- 6
85
+ L <- 3
86
+ curve( dbeta( x , W+1 , L+1 ) , from=0 , to=1 )
87
+ # quadratic approximation
88
+ curve( dnorm( x , 0.67 , 0.16 ) , lty=2 , add=TRUE )
89
+
90
+ ## R code 2.8
91
+ n_samples <- 1000
92
+ p <- rep( NA , n_samples )
93
+ p[1] <- 0.5
94
+ W <- 6
95
+ L <- 3
96
+ for ( i in 2:n_samples ) {
97
+ p_new <- rnorm( 1 , p[i-1] , 0.1 )
98
+ if ( p_new < 0 ) p_new <- abs( p_new )
99
+ if ( p_new > 1 ) p_new <- 2 - p_new
100
+ q0 <- dbinom( W , W+L , p[i-1] )
101
+ q1 <- dbinom( W , W+L , p_new )
102
+ p[i] <- ifelse( runif(1) < q1/q0 , p_new , p[i-1] )
103
+ }
104
+
105
+ ## R code 2.9
106
+ dens( p , xlim=c(0,1) )
107
+ curve( dbeta( x , W+1 , L+1 ) , lty=2 , add=TRUE )
108
+
109
+ ## R code 3.1
110
+ Pr_Positive_Vampire <- 0.95
111
+ Pr_Positive_Mortal <- 0.01
112
+ Pr_Vampire <- 0.001
113
+ Pr_Positive <- Pr_Positive_Vampire * Pr_Vampire +
114
+ Pr_Positive_Mortal * ( 1 - Pr_Vampire )
115
+ ( Pr_Vampire_Positive <- Pr_Positive_Vampire*Pr_Vampire / Pr_Positive )
116
+
117
+ ## R code 3.2
118
+ p_grid <- seq( from=0 , to=1 , length.out=1000 )
119
+ prob_p <- rep( 1 , 1000 )
120
+ prob_data <- dbinom( 6 , size=9 , prob=p_grid )
121
+ posterior <- prob_data * prob_p
122
+ posterior <- posterior / sum(posterior)
123
+
124
+ ## R code 3.3
125
+ samples <- sample( p_grid , prob=posterior , size=1e4 , replace=TRUE )
126
+
127
+ ## R code 3.4
128
+ plot( samples )
129
+
130
+ ## R code 3.5
131
+ library(rethinking)
132
+ dens( samples )
133
+
134
+ ## R code 3.6
135
+ # add up posterior probability where p < 0.5
136
+ sum( posterior[ p_grid < 0.5 ] )
137
+
138
+ ## R code 3.7
139
+ sum( samples < 0.5 ) / 1e4
140
+
141
+ ## R code 3.8
142
+ sum( samples > 0.5 & samples < 0.75 ) / 1e4
143
+
144
+ ## R code 3.9
145
+ quantile( samples , 0.8 )
146
+
147
+ ## R code 3.10
148
+ quantile( samples , c( 0.1 , 0.9 ) )
149
+
150
+ ## R code 3.11
151
+ p_grid <- seq( from=0 , to=1 , length.out=1000 )
152
+ prior <- rep(1,1000)
153
+ likelihood <- dbinom( 3 , size=3 , prob=p_grid )
154
+ posterior <- likelihood * prior
155
+ posterior <- posterior / sum(posterior)
156
+ samples <- sample( p_grid , size=1e4 , replace=TRUE , prob=posterior )
157
+
158
+ ## R code 3.12
159
+ PI( samples , prob=0.5 )
160
+
161
+ ## R code 3.13
162
+ HPDI( samples , prob=0.5 )
163
+
164
+ ## R code 3.14
165
+ p_grid[ which.max(posterior) ]
166
+
167
+ ## R code 3.15
168
+ chainmode( samples , adj=0.01 )
169
+
170
+ ## R code 3.16
171
+ mean( samples )
172
+ median( samples )
173
+
174
+ ## R code 3.17
175
+ sum( posterior*abs( 0.5 - p_grid ) )
176
+
177
+ ## R code 3.18
178
+ loss <- sapply( p_grid , function(d) sum( posterior*abs( d - p_grid ) ) )
179
+
180
+ ## R code 3.19
181
+ p_grid[ which.min(loss) ]
182
+
183
+ ## R code 3.20
184
+ dbinom( 0:2 , size=2 , prob=0.7 )
185
+
186
+ ## R code 3.21
187
+ rbinom( 1 , size=2 , prob=0.7 )
188
+
189
+ ## R code 3.22
190
+ rbinom( 10 , size=2 , prob=0.7 )
191
+
192
+ ## R code 3.23
193
+ dummy_w <- rbinom( 1e5 , size=2 , prob=0.7 )
194
+ table(dummy_w)/1e5
195
+
196
+ ## R code 3.24
197
+ dummy_w <- rbinom( 1e5 , size=9 , prob=0.7 )
198
+ simplehist( dummy_w , xlab="dummy water count" )
199
+
200
+ ## R code 3.25
201
+ w <- rbinom( 1e4 , size=9 , prob=0.6 )
202
+
203
+ ## R code 3.26
204
+ w <- rbinom( 1e4 , size=9 , prob=samples )
205
+
206
+ ## R code 3.27
207
+ p_grid <- seq( from=0 , to=1 , length.out=1000 )
208
+ prior <- rep( 1 , 1000 )
209
+ likelihood <- dbinom( 6 , size=9 , prob=p_grid )
210
+ posterior <- likelihood * prior
211
+ posterior <- posterior / sum(posterior)
212
+ set.seed(100)
213
+ samples <- sample( p_grid , prob=posterior , size=1e4 , replace=TRUE )
214
+
215
+ ## R code 3.28
216
+ birth1 <- c(1,0,0,0,1,1,0,1,0,1,0,0,1,1,0,1,1,0,0,0,1,0,0,0,1,0,
217
+ 0,0,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1,0,1,0,0,1,1,0,1,0,0,0,0,0,0,0,
218
+ 1,1,0,1,0,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,1,1,1,0,0,1,0,1,1,0,
219
+ 1,0,1,1,1,0,1,1,1,1)
220
+ birth2 <- c(0,1,0,1,0,1,1,1,0,0,1,1,1,1,1,0,0,1,1,1,0,0,1,1,1,0,
221
+ 1,1,1,0,1,1,1,0,1,0,0,1,1,1,1,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,
222
+ 1,1,1,0,1,1,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,1,1,
223
+ 0,0,0,1,1,1,0,0,0,0)
224
+
225
+ ## R code 3.29
226
+ library(rethinking)
227
+ data(homeworkch3)
228
+
229
+ ## R code 3.30
230
+ sum(birth1) + sum(birth2)
231
+
232
+ ## R code 4.1
233
+ pos <- replicate( 1000 , sum( runif(16,-1,1) ) )
234
+
235
+ ## R code 4.2
236
+ prod( 1 + runif(12,0,0.1) )
237
+
238
+ ## R code 4.3
239
+ growth <- replicate( 10000 , prod( 1 + runif(12,0,0.1) ) )
240
+ dens( growth , norm.comp=TRUE )
241
+
242
+ ## R code 4.4
243
+ big <- replicate( 10000 , prod( 1 + runif(12,0,0.5) ) )
244
+ small <- replicate( 10000 , prod( 1 + runif(12,0,0.01) ) )
245
+
246
+ ## R code 4.5
247
+ log.big <- replicate( 10000 , log(prod(1 + runif(12,0,0.5))) )
248
+
249
+ ## R code 4.6
250
+ w <- 6; n <- 9;
251
+ p_grid <- seq(from=0,to=1,length.out=100)
252
+ posterior <- dbinom(w,n,p_grid)*dunif(p_grid,0,1)
253
+ posterior <- posterior/sum(posterior)
254
+
255
+ ## R code 4.7
256
+ library(rethinking)
257
+ data(Howell1)
258
+ d <- Howell1
259
+
260
+ ## R code 4.8
261
+ str( d )
262
+
263
+ ## R code 4.9
264
+ precis( d )
265
+
266
+ ## R code 4.10
267
+ d$height
268
+
269
+ ## R code 4.11
270
+ d2 <- d[ d$age >= 18 , ]
271
+
272
+ ## R code 4.12
273
+ curve( dnorm( x , 178 , 20 ) , from=100 , to=250 )
274
+
275
+ ## R code 4.13
276
+ curve( dunif( x , 0 , 50 ) , from=-10 , to=60 )
277
+
278
+ ## R code 4.14
279
+ sample_mu <- rnorm( 1e4 , 178 , 20 )
280
+ sample_sigma <- runif( 1e4 , 0 , 50 )
281
+ prior_h <- rnorm( 1e4 , sample_mu , sample_sigma )
282
+ dens( prior_h )
283
+
284
+ ## R code 4.15
285
+ sample_mu <- rnorm( 1e4 , 178 , 100 )
286
+ prior_h <- rnorm( 1e4 , sample_mu , sample_sigma )
287
+ dens( prior_h )
288
+
289
+ ## R code 4.16
290
+ mu.list <- seq( from=150, to=160 , length.out=100 )
291
+ sigma.list <- seq( from=7 , to=9 , length.out=100 )
292
+ post <- expand.grid( mu=mu.list , sigma=sigma.list )
293
+ post$LL <- sapply( 1:nrow(post) , function(i) sum(
294
+ dnorm( d2$height , post$mu[i] , post$sigma[i] , log=TRUE ) ) )
295
+ post$prod <- post$LL + dnorm( post$mu , 178 , 20 , TRUE ) +
296
+ dunif( post$sigma , 0 , 50 , TRUE )
297
+ post$prob <- exp( post$prod - max(post$prod) )
298
+
299
+ ## R code 4.17
300
+ contour_xyz( post$mu , post$sigma , post$prob )
301
+
302
+ ## R code 4.18
303
+ image_xyz( post$mu , post$sigma , post$prob )
304
+
305
+ ## R code 4.19
306
+ sample.rows <- sample( 1:nrow(post) , size=1e4 , replace=TRUE ,
307
+ prob=post$prob )
308
+ sample.mu <- post$mu[ sample.rows ]
309
+ sample.sigma <- post$sigma[ sample.rows ]
310
+
311
+ ## R code 4.20
312
+ plot( sample.mu , sample.sigma , cex=0.5 , pch=16 , col=col.alpha(rangi2,0.1) )
313
+
314
+ ## R code 4.21
315
+ dens( sample.mu )
316
+ dens( sample.sigma )
317
+
318
+ ## R code 4.22
319
+ PI( sample.mu )
320
+ PI( sample.sigma )
321
+
322
+ ## R code 4.23
323
+ d3 <- sample( d2$height , size=20 )
324
+
325
+ ## R code 4.24
326
+ mu.list <- seq( from=150, to=170 , length.out=200 )
327
+ sigma.list <- seq( from=4 , to=20 , length.out=200 )
328
+ post2 <- expand.grid( mu=mu.list , sigma=sigma.list )
329
+ post2$LL <- sapply( 1:nrow(post2) , function(i)
330
+ sum( dnorm( d3 , mean=post2$mu[i] , sd=post2$sigma[i] ,
331
+ log=TRUE ) ) )
332
+ post2$prod <- post2$LL + dnorm( post2$mu , 178 , 20 , TRUE ) +
333
+ dunif( post2$sigma , 0 , 50 , TRUE )
334
+ post2$prob <- exp( post2$prod - max(post2$prod) )
335
+ sample2.rows <- sample( 1:nrow(post2) , size=1e4 , replace=TRUE ,
336
+ prob=post2$prob )
337
+ sample2.mu <- post2$mu[ sample2.rows ]
338
+ sample2.sigma <- post2$sigma[ sample2.rows ]
339
+ plot( sample2.mu , sample2.sigma , cex=0.5 ,
340
+ col=col.alpha(rangi2,0.1) ,
341
+ xlab="mu" , ylab="sigma" , pch=16 )
342
+
343
+ ## R code 4.25
344
+ dens( sample2.sigma , norm.comp=TRUE )
345
+
346
+ ## R code 4.26
347
+ library(rethinking)
348
+ data(Howell1)
349
+ d <- Howell1
350
+ d2 <- d[ d$age >= 18 , ]
351
+
352
+ ## R code 4.27
353
+ flist <- alist(
354
+ height ~ dnorm( mu , sigma ) ,
355
+ mu ~ dnorm( 178 , 20 ) ,
356
+ sigma ~ dunif( 0 , 50 )
357
+ )
358
+
359
+ ## R code 4.28
360
+ m4.1 <- quap( flist , data=d2 )
361
+
362
+ ## R code 4.29
363
+ precis( m4.1 )
364
+
365
+ ## R code 4.30
366
+ start <- list(
367
+ mu=mean(d2$height),
368
+ sigma=sd(d2$height)
369
+ )
370
+ m4.1 <- quap( flist , data=d2 , start=start )
371
+
372
+ ## R code 4.31
373
+ m4.2 <- quap(
374
+ alist(
375
+ height ~ dnorm( mu , sigma ) ,
376
+ mu ~ dnorm( 178 , 0.1 ) ,
377
+ sigma ~ dunif( 0 , 50 )
378
+ ) , data=d2 )
379
+ precis( m4.2 )
380
+
381
+ ## R code 4.32
382
+ vcov( m4.1 )
383
+
384
+ ## R code 4.33
385
+ diag( vcov( m4.1 ) )
386
+ cov2cor( vcov( m4.1 ) )
387
+
388
+ ## R code 4.34
389
+ library(rethinking)
390
+ post <- extract.samples( m4.1 , n=1e4 )
391
+ head(post)
392
+
393
+ ## R code 4.35
394
+ precis(post)
395
+
396
+ ## R code 4.36
397
+ library(MASS)
398
+ post <- mvrnorm( n=1e4 , mu=coef(m4.1) , Sigma=vcov(m4.1) )
399
+
400
+ ## R code 4.37
401
+ library(rethinking)
402
+ data(Howell1); d <- Howell1; d2 <- d[ d$age >= 18 , ]
403
+ plot( d2$height ~ d2$weight )
404
+
405
+ ## R code 4.38
406
+ set.seed(2971)
407
+ N <- 100 # 100 lines
408
+ a <- rnorm( N , 178 , 20 )
409
+ b <- rnorm( N , 0 , 10 )
410
+
411
+ ## R code 4.39
412
+ plot( NULL , xlim=range(d2$weight) , ylim=c(-100,400) ,
413
+ xlab="weight" , ylab="height" )
414
+ abline( h=0 , lty=2 )
415
+ abline( h=272 , lty=1 , lwd=0.5 )
416
+ mtext( "b ~ dnorm(0,10)" )
417
+ xbar <- mean(d2$weight)
418
+ for ( i in 1:N ) curve( a[i] + b[i]*(x - xbar) ,
419
+ from=min(d2$weight) , to=max(d2$weight) , add=TRUE ,
420
+ col=col.alpha("black",0.2) )
421
+
422
+ ## R code 4.40
423
+ b <- rlnorm( 1e4 , 0 , 1 )
424
+ dens( b , xlim=c(0,5) , adj=0.1 )
425
+
426
+ ## R code 4.41
427
+ set.seed(2971)
428
+ N <- 100 # 100 lines
429
+ a <- rnorm( N , 178 , 20 )
430
+ b <- rlnorm( N , 0 , 1 )
431
+
432
+ ## R code 4.42
433
+ # load data again, since it's a long way back
434
+ library(rethinking)
435
+ data(Howell1); d <- Howell1; d2 <- d[ d$age >= 18 , ]
436
+
437
+ # define the average weight, x-bar
438
+ xbar <- mean(d2$weight)
439
+
440
+ # fit model
441
+ m4.3 <- quap(
442
+ alist(
443
+ height ~ dnorm( mu , sigma ) ,
444
+ mu <- a + b*( weight - xbar ) ,
445
+ a ~ dnorm( 178 , 20 ) ,
446
+ b ~ dlnorm( 0 , 1 ) ,
447
+ sigma ~ dunif( 0 , 50 )
448
+ ) , data=d2 )
449
+
450
+ ## R code 4.43
451
+ m4.3b <- quap(
452
+ alist(
453
+ height ~ dnorm( mu , sigma ) ,
454
+ mu <- a + exp(log_b)*( weight - xbar ),
455
+ a ~ dnorm( 178 , 20 ) ,
456
+ log_b ~ dnorm( 0 , 1 ) ,
457
+ sigma ~ dunif( 0 , 50 )
458
+ ) , data=d2 )
459
+
460
+ ## R code 4.44
461
+ precis( m4.3 )
462
+
463
+ ## R code 4.45
464
+ round( vcov( m4.3 ) , 3 )
465
+
466
+ ## R code 4.46
467
+ plot( height ~ weight , data=d2 , col=rangi2 )
468
+ post <- extract.samples( m4.3 )
469
+ a_map <- mean(post$a)
470
+ b_map <- mean(post$b)
471
+ curve( a_map + b_map*(x - xbar) , add=TRUE )
472
+
473
+ ## R code 4.47
474
+ post <- extract.samples( m4.3 )
475
+ post[1:5,]
476
+
477
+ ## R code 4.48
478
+ N <- 10
479
+ dN <- d2[ 1:N , ]
480
+ mN <- quap(
481
+ alist(
482
+ height ~ dnorm( mu , sigma ) ,
483
+ mu <- a + b*( weight - mean(weight) ) ,
484
+ a ~ dnorm( 178 , 20 ) ,
485
+ b ~ dlnorm( 0 , 1 ) ,
486
+ sigma ~ dunif( 0 , 50 )
487
+ ) , data=dN )
488
+
489
+ ## R code 4.49
490
+ # extract 20 samples from the posterior
491
+ post <- extract.samples( mN , n=20 )
492
+
493
+ # display raw data and sample size
494
+ plot( dN$weight , dN$height ,
495
+ xlim=range(d2$weight) , ylim=range(d2$height) ,
496
+ col=rangi2 , xlab="weight" , ylab="height" )
497
+ mtext(concat("N = ",N))
498
+
499
+ # plot the lines, with transparency
500
+ for ( i in 1:20 )
501
+ curve( post$a[i] + post$b[i]*(x-mean(dN$weight)) ,
502
+ col=col.alpha("black",0.3) , add=TRUE )
503
+
504
+ ## R code 4.50
505
+ post <- extract.samples( m4.3 )
506
+ mu_at_50 <- post$a + post$b * ( 50 - xbar )
507
+
508
+ ## R code 4.51
509
+ dens( mu_at_50 , col=rangi2 , lwd=2 , xlab="mu|weight=50" )
510
+
511
+ ## R code 4.52
512
+ PI( mu_at_50 , prob=0.89 )
513
+
514
+ ## R code 4.53
515
+ mu <- link( m4.3 )
516
+ str(mu)
517
+
518
+ ## R code 4.54
519
+ # define sequence of weights to compute predictions for
520
+ # these values will be on the horizontal axis
521
+ weight.seq <- seq( from=25 , to=70 , by=1 )
522
+
523
+ # use link to compute mu
524
+ # for each sample from posterior
525
+ # and for each weight in weight.seq
526
+ mu <- link( m4.3 , data=data.frame(weight=weight.seq) )
527
+ str(mu)
528
+
529
+ ## R code 4.55
530
+ # use type="n" to hide raw data
531
+ plot( height ~ weight , d2 , type="n" )
532
+
533
+ # loop over samples and plot each mu value
534
+ for ( i in 1:100 )
535
+ points( weight.seq , mu[i,] , pch=16 , col=col.alpha(rangi2,0.1) )
536
+
537
+ ## R code 4.56
538
+ # summarize the distribution of mu
539
+ mu.mean <- apply( mu , 2 , mean )
540
+ mu.PI <- apply( mu , 2 , PI , prob=0.89 )
541
+
542
+ ## R code 4.57
543
+ # plot raw data
544
+ # fading out points to make line and interval more visible
545
+ plot( height ~ weight , data=d2 , col=col.alpha(rangi2,0.5) )
546
+
547
+ # plot the MAP line, aka the mean mu for each weight
548
+ lines( weight.seq , mu.mean )
549
+
550
+ # plot a shaded region for 89% PI
551
+ shade( mu.PI , weight.seq )
552
+
553
+ ## R code 4.58
554
+ post <- extract.samples(m4.3)
555
+ mu.link <- function(weight) post$a + post$b*( weight - xbar )
556
+ weight.seq <- seq( from=25 , to=70 , by=1 )
557
+ mu <- sapply( weight.seq , mu.link )
558
+ mu.mean <- apply( mu , 2 , mean )
559
+ mu.CI <- apply( mu , 2 , PI , prob=0.89 )
560
+
561
+ ## R code 4.59
562
+ sim.height <- sim( m4.3 , data=list(weight=weight.seq) )
563
+ str(sim.height)
564
+
565
+ ## R code 4.60
566
+ height.PI <- apply( sim.height , 2 , PI , prob=0.89 )
567
+
568
+ ## R code 4.61
569
+ # plot raw data
570
+ plot( height ~ weight , d2 , col=col.alpha(rangi2,0.5) )
571
+
572
+ # draw MAP line
573
+ lines( weight.seq , mu.mean )
574
+
575
+ # draw HPDI region for line
576
+ shade( mu.HPDI , weight.seq )
577
+
578
+ # draw PI region for simulated heights
579
+ shade( height.PI , weight.seq )
580
+
581
+ ## R code 4.62
582
+ sim.height <- sim( m4.3 , data=list(weight=weight.seq) , n=1e4 )
583
+ height.PI <- apply( sim.height , 2 , PI , prob=0.89 )
584
+
585
+ ## R code 4.63
586
+ post <- extract.samples(m4.3)
587
+ weight.seq <- 25:70
588
+ sim.height <- sapply( weight.seq , function(weight)
589
+ rnorm(
590
+ n=nrow(post) ,
591
+ mean=post$a + post$b*( weight - xbar ) ,
592
+ sd=post$sigma ) )
593
+ height.PI <- apply( sim.height , 2 , PI , prob=0.89 )
594
+
595
+ ## R code 4.64
596
+ library(rethinking)
597
+ data(Howell1)
598
+ d <- Howell1
599
+
600
+ ## R code 4.65
601
+ d$weight_s <- ( d$weight - mean(d$weight) )/sd(d$weight)
602
+ d$weight_s2 <- d$weight_s^2
603
+ m4.5 <- quap(
604
+ alist(
605
+ height ~ dnorm( mu , sigma ) ,
606
+ mu <- a + b1*weight_s + b2*weight_s2 ,
607
+ a ~ dnorm( 178 , 20 ) ,
608
+ b1 ~ dlnorm( 0 , 1 ) ,
609
+ b2 ~ dnorm( 0 , 1 ) ,
610
+ sigma ~ dunif( 0 , 50 )
611
+ ) , data=d )
612
+
613
+ ## R code 4.66
614
+ precis( m4.5 )
615
+
616
+ ## R code 4.67
617
+ weight.seq <- seq( from=-2.2 , to=2 , length.out=30 )
618
+ pred_dat <- list( weight_s=weight.seq , weight_s2=weight.seq^2 )
619
+ mu <- link( m4.5 , data=pred_dat )
620
+ mu.mean <- apply( mu , 2 , mean )
621
+ mu.PI <- apply( mu , 2 , PI , prob=0.89 )
622
+ sim.height <- sim( m4.5 , data=pred_dat )
623
+ height.PI <- apply( sim.height , 2 , PI , prob=0.89 )
624
+
625
+ ## R code 4.68
626
+ plot( height ~ weight_s , d , col=col.alpha(rangi2,0.5) )
627
+ lines( weight.seq , mu.mean )
628
+ shade( mu.PI , weight.seq )
629
+ shade( height.PI , weight.seq )
630
+
631
+ ## R code 4.69
632
+ d$weight_s3 <- d$weight_s^3
633
+ m4.6 <- quap(
634
+ alist(
635
+ height ~ dnorm( mu , sigma ) ,
636
+ mu <- a + b1*weight_s + b2*weight_s2 + b3*weight_s3 ,
637
+ a ~ dnorm( 178 , 20 ) ,
638
+ b1 ~ dlnorm( 0 , 1 ) ,
639
+ b2 ~ dnorm( 0 , 10 ) ,
640
+ b3 ~ dnorm( 0 , 10 ) ,
641
+ sigma ~ dunif( 0 , 50 )
642
+ ) , data=d )
643
+
644
+ ## R code 4.70
645
+ plot( height ~ weight_s , d , col=col.alpha(rangi2,0.5) , xaxt="n" )
646
+
647
+ ## R code 4.71
648
+ at <- c(-2,-1,0,1,2)
649
+ labels <- at*sd(d$weight) + mean(d$weight)
650
+ axis( side=1 , at=at , labels=round(labels,1) )
651
+
652
+ ## R code 4.72
653
+ library(rethinking)
654
+ data(cherry_blossoms)
655
+ d <- cherry_blossoms
656
+ precis(d)
657
+
658
+ ## R code 4.73
659
+ d2 <- d[ complete.cases(d$doy) , ] # complete cases on doy
660
+ num_knots <- 15
661
+ knot_list <- quantile( d2$year , probs=seq(0,1,length.out=num_knots) )
662
+
663
+ ## R code 4.74
664
+ library(splines)
665
+ B <- bs(d2$year,
666
+ knots=knot_list[-c(1,num_knots)] ,
667
+ degree=3 , intercept=TRUE )
668
+
669
+ ## R code 4.75
670
+ plot( NULL , xlim=range(d2$year) , ylim=c(0,1) , xlab="year" , ylab="basis" )
671
+ for ( i in 1:ncol(B) ) lines( d2$year , B[,i] )
672
+
673
+ ## R code 4.76
674
+ m4.7 <- quap(
675
+ alist(
676
+ D ~ dnorm( mu , sigma ) ,
677
+ mu <- a + B %*% w ,
678
+ a ~ dnorm(100,10),
679
+ w ~ dnorm(0,10),
680
+ sigma ~ dexp(1)
681
+ ), data=list( D=d2$doy , B=B ) ,
682
+ start=list( w=rep( 0 , ncol(B) ) ) )
683
+
684
+ ## R code 4.77
685
+ post <- extract.samples( m4.7 )
686
+ w <- apply( post$w , 2 , mean )
687
+ plot( NULL , xlim=range(d2$year) , ylim=c(-6,6) ,
688
+ xlab="year" , ylab="basis * weight" )
689
+ for ( i in 1:ncol(B) ) lines( d2$year , w[i]*B[,i] )
690
+
691
+ ## R code 4.78
692
+ mu <- link( m4.7 )
693
+ mu_PI <- apply(mu,2,PI,0.97)
694
+ plot( d2$year , d2$doy , col=col.alpha(rangi2,0.3) , pch=16 )
695
+ shade( mu_PI , d2$year , col=col.alpha("black",0.5) )
696
+
697
+ ## R code 4.79
698
+ m4.7alt <- quap(
699
+ alist(
700
+ D ~ dnorm( mu , sigma ) ,
701
+ mu <- a + sapply( 1:827 , function(i) sum( B[i,]*w ) ) ,
702
+ a ~ dnorm(100,1),
703
+ w ~ dnorm(0,10),
704
+ sigma ~ dexp(1)
705
+ ),
706
+ data=list( D=d2$doy , B=B ) ,
707
+ start=list( w=rep( 0 , ncol(B) ) ) )
708
+
709
+ ## R code 5.1
710
+ # load data and copy
711
+ library(rethinking)
712
+ data(WaffleDivorce)
713
+ d <- WaffleDivorce
714
+
715
+ # standardize variables
716
+ d$D <- standardize( d$Divorce )
717
+ d$M <- standardize( d$Marriage )
718
+ d$A <- standardize( d$MedianAgeMarriage )
719
+
720
+ ## R code 5.2
721
+ sd( d$MedianAgeMarriage )
722
+
723
+ ## R code 5.3
724
+ m5.1 <- quap(
725
+ alist(
726
+ D ~ dnorm( mu , sigma ) ,
727
+ mu <- a + bA * A ,
728
+ a ~ dnorm( 0 , 0.2 ) ,
729
+ bA ~ dnorm( 0 , 0.5 ) ,
730
+ sigma ~ dexp( 1 )
731
+ ) , data = d )
732
+
733
+ ## R code 5.4
734
+ set.seed(10)
735
+ prior <- extract.prior( m5.1 )
736
+ mu <- link( m5.1 , post=prior , data=list( A=c(-2,2) ) )
737
+ plot( NULL , xlim=c(-2,2) , ylim=c(-2,2) )
738
+ for ( i in 1:50 ) lines( c(-2,2) , mu[i,] , col=col.alpha("black",0.4) )
739
+
740
+ ## R code 5.5
741
+ # compute percentile interval of mean
742
+ A_seq <- seq( from=-3 , to=3.2 , length.out=30 )
743
+ mu <- link( m5.1 , data=list(A=A_seq) )
744
+ mu.mean <- apply( mu , 2, mean )
745
+ mu.PI <- apply( mu , 2 , PI )
746
+
747
+ # plot it all
748
+ plot( D ~ A , data=d , col=rangi2 )
749
+ lines( A_seq , mu.mean , lwd=2 )
750
+ shade( mu.PI , A_seq )
751
+
752
+ ## R code 5.6
753
+ m5.2 <- quap(
754
+ alist(
755
+ D ~ dnorm( mu , sigma ) ,
756
+ mu <- a + bM * M ,
757
+ a ~ dnorm( 0 , 0.2 ) ,
758
+ bM ~ dnorm( 0 , 0.5 ) ,
759
+ sigma ~ dexp( 1 )
760
+ ) , data = d )
761
+
762
+ ## R code 5.7
763
+ library(dagitty)
764
+ dag5.1 <- dagitty( "dag{ A -> D; A -> M; M -> D }" )
765
+ coordinates(dag5.1) <- list( x=c(A=0,D=1,M=2) , y=c(A=0,D=1,M=0) )
766
+ drawdag( dag5.1 )
767
+
768
+ ## R code 5.8
769
+ DMA_dag2 <- dagitty('dag{ D <- A -> M }')
770
+ impliedConditionalIndependencies( DMA_dag2 )
771
+
772
+ ## R code 5.9
773
+ DMA_dag1 <- dagitty('dag{ D <- A -> M -> D }')
774
+ impliedConditionalIndependencies( DMA_dag1 )
775
+
776
+ ## R code 5.10
777
+ m5.3 <- quap(
778
+ alist(
779
+ D ~ dnorm( mu , sigma ) ,
780
+ mu <- a + bM*M + bA*A ,
781
+ a ~ dnorm( 0 , 0.2 ) ,
782
+ bM ~ dnorm( 0 , 0.5 ) ,
783
+ bA ~ dnorm( 0 , 0.5 ) ,
784
+ sigma ~ dexp( 1 )
785
+ ) , data = d )
786
+ precis( m5.3 )
787
+
788
+ ## R code 5.11
789
+ plot( coeftab(m5.1,m5.2,m5.3), par=c("bA","bM") )
790
+
791
+ ## R code 5.12
792
+ N <- 50 # number of simulated States
793
+ age <- rnorm( N ) # sim A
794
+ mar <- rnorm( N , -age ) # sim A -> M
795
+ div <- rnorm( N , age ) # sim A -> D
796
+
797
+ ## R code 5.13
798
+ m5.4 <- quap(
799
+ alist(
800
+ M ~ dnorm( mu , sigma ) ,
801
+ mu <- a + bAM * A ,
802
+ a ~ dnorm( 0 , 0.2 ) ,
803
+ bAM ~ dnorm( 0 , 0.5 ) ,
804
+ sigma ~ dexp( 1 )
805
+ ) , data = d )
806
+
807
+ ## R code 5.14
808
+ mu <- link(m5.4)
809
+ mu_mean <- apply( mu , 2 , mean )
810
+ mu_resid <- d$M - mu_mean
811
+
812
+ ## R code 5.15
813
+ # call link without specifying new data
814
+ # so it uses original data
815
+ mu <- link( m5.3 )
816
+
817
+ # summarize samples across cases
818
+ mu_mean <- apply( mu , 2 , mean )
819
+ mu_PI <- apply( mu , 2 , PI )
820
+
821
+ # simulate observations
822
+ # again no new data, so uses original data
823
+ D_sim <- sim( m5.3 , n=1e4 )
824
+ D_PI <- apply( D_sim , 2 , PI )
825
+
826
+ ## R code 5.16
827
+ plot( mu_mean ~ d$D , col=rangi2 , ylim=range(mu_PI) ,
828
+ xlab="Observed divorce" , ylab="Predicted divorce" )
829
+ abline( a=0 , b=1 , lty=2 )
830
+ for ( i in 1:nrow(d) ) lines( rep(d$D[i],2) , mu_PI[,i] , col=rangi2 )
831
+
832
+ ## R code 5.17
833
+ identify( x=d$D , y=mu_mean , labels=d$Loc )
834
+
835
+ ## R code 5.18
836
+ N <- 100 # number of cases
837
+ x_real <- rnorm( N ) # x_real as Gaussian with mean 0 and stddev 1
838
+ x_spur <- rnorm( N , x_real ) # x_spur as Gaussian with mean=x_real
839
+ y <- rnorm( N , x_real ) # y as Gaussian with mean=x_real
840
+ d <- data.frame(y,x_real,x_spur) # bind all together in data frame
841
+
842
+ ## R code 5.19
843
+ data(WaffleDivorce)
844
+ d <- list()
845
+ d$A <- standardize( WaffleDivorce$MedianAgeMarriage )
846
+ d$D <- standardize( WaffleDivorce$Divorce )
847
+ d$M <- standardize( WaffleDivorce$Marriage )
848
+
849
+ m5.3_A <- quap(
850
+ alist(
851
+ ## A -> D <- M
852
+ D ~ dnorm( mu , sigma ) ,
853
+ mu <- a + bM*M + bA*A ,
854
+ a ~ dnorm( 0 , 0.2 ) ,
855
+ bM ~ dnorm( 0 , 0.5 ) ,
856
+ bA ~ dnorm( 0 , 0.5 ) ,
857
+ sigma ~ dexp( 1 ),
858
+ ## A -> M
859
+ M ~ dnorm( mu_M , sigma_M ),
860
+ mu_M <- aM + bAM*A,
861
+ aM ~ dnorm( 0 , 0.2 ),
862
+ bAM ~ dnorm( 0 , 0.5 ),
863
+ sigma_M ~ dexp( 1 )
864
+ ) , data = d )
865
+
866
+ ## R code 5.20
867
+ A_seq <- seq( from=-2 , to=2 , length.out=30 )
868
+
869
+ ## R code 5.21
870
+ # prep data
871
+ sim_dat <- data.frame( A=A_seq )
872
+
873
+ # simulate M and then D, using A_seq
874
+ s <- sim( m5.3_A , data=sim_dat , vars=c("M","D") )
875
+
876
+ ## R code 5.22
877
+ plot( sim_dat$A , colMeans(s$D) , ylim=c(-2,2) , type="l" ,
878
+ xlab="manipulated A" , ylab="counterfactual D" )
879
+ shade( apply(s$D,2,PI) , sim_dat$A )
880
+ mtext( "Total counterfactual effect of A on D" )
881
+
882
+ ## R code 5.23
883
+ # new data frame, standardized to mean 26.1 and std dev 1.24
884
+ sim2_dat <- data.frame( A=(c(20,30)-26.1)/1.24 )
885
+ s2 <- sim( m5.3_A , data=sim2_dat , vars=c("M","D") )
886
+ mean( s2$D[,2] - s2$D[,1] )
887
+
888
+ ## R code 5.24
889
+ sim_dat <- data.frame( M=seq(from=-2,to=2,length.out=30) , A=0 )
890
+ s <- sim( m5.3_A , data=sim_dat , vars="D" )
891
+
892
+ plot( sim_dat$M , colMeans(s) , ylim=c(-2,2) , type="l" ,
893
+ xlab="manipulated M" , ylab="counterfactual D" )
894
+ shade( apply(s,2,PI) , sim_dat$M )
895
+ mtext( "Total counterfactual effect of M on D" )
896
+
897
+ ## R code 5.25
898
+ A_seq <- seq( from=-2 , to=2 , length.out=30 )
899
+
900
+ ## R code 5.26
901
+ post <- extract.samples( m5.3_A )
902
+ M_sim <- with( post , sapply( 1:30 ,
903
+ function(i) rnorm( 1e3 , aM + bAM*A_seq[i] , sigma_M ) ) )
904
+
905
+ ## R code 5.27
906
+ D_sim <- with( post , sapply( 1:30 ,
907
+ function(i) rnorm( 1e3 , a + bA*A_seq[i] + bM*M_sim[,i] , sigma ) ) )
908
+
909
+ ## R code 5.28
910
+ library(rethinking)
911
+ data(milk)
912
+ d <- milk
913
+ str(d)
914
+
915
+ ## R code 5.29
916
+ d$K <- standardize( d$kcal.per.g )
917
+ d$N <- standardize( d$neocortex.perc )
918
+ d$M <- standardize( log(d$mass) )
919
+
920
+ ## R code 5.30
921
+ m5.5_draft <- quap(
922
+ alist(
923
+ K ~ dnorm( mu , sigma ) ,
924
+ mu <- a + bN*N ,
925
+ a ~ dnorm( 0 , 1 ) ,
926
+ bN ~ dnorm( 0 , 1 ) ,
927
+ sigma ~ dexp( 1 )
928
+ ) , data=d )
929
+
930
+ ## R code 5.31
931
+ d$neocortex.perc
932
+
933
+ ## R code 5.32
934
+ dcc <- d[ complete.cases(d$K,d$N,d$M) , ]
935
+
936
+ ## R code 5.33
937
+ m5.5_draft <- quap(
938
+ alist(
939
+ K ~ dnorm( mu , sigma ) ,
940
+ mu <- a + bN*N ,
941
+ a ~ dnorm( 0 , 1 ) ,
942
+ bN ~ dnorm( 0 , 1 ) ,
943
+ sigma ~ dexp( 1 )
944
+ ) , data=dcc )
945
+
946
+ ## R code 5.34
947
+ prior <- extract.prior( m5.5_draft )
948
+ xseq <- c(-2,2)
949
+ mu <- link( m5.5_draft , post=prior , data=list(N=xseq) )
950
+ plot( NULL , xlim=xseq , ylim=xseq )
951
+ for ( i in 1:50 ) lines( xseq , mu[i,] , col=col.alpha("black",0.3) )
952
+
953
+ ## R code 5.35
954
+ m5.5 <- quap(
955
+ alist(
956
+ K ~ dnorm( mu , sigma ) ,
957
+ mu <- a + bN*N ,
958
+ a ~ dnorm( 0 , 0.2 ) ,
959
+ bN ~ dnorm( 0 , 0.5 ) ,
960
+ sigma ~ dexp( 1 )
961
+ ) , data=dcc )
962
+
963
+ ## R code 5.36
964
+ precis( m5.5 )
965
+
966
+ ## R code 5.37
967
+ xseq <- seq( from=min(dcc$N)-0.15 , to=max(dcc$N)+0.15 , length.out=30 )
968
+ mu <- link( m5.5 , data=list(N=xseq) )
969
+ mu_mean <- apply(mu,2,mean)
970
+ mu_PI <- apply(mu,2,PI)
971
+ plot( K ~ N , data=dcc )
972
+ lines( xseq , mu_mean , lwd=2 )
973
+ shade( mu_PI , xseq )
974
+
975
+ ## R code 5.38
976
+ m5.6 <- quap(
977
+ alist(
978
+ K ~ dnorm( mu , sigma ) ,
979
+ mu <- a + bM*M ,
980
+ a ~ dnorm( 0 , 0.2 ) ,
981
+ bM ~ dnorm( 0 , 0.5 ) ,
982
+ sigma ~ dexp( 1 )
983
+ ) , data=dcc )
984
+ precis(m5.6)
985
+
986
+ ## R code 5.39
987
+ m5.7 <- quap(
988
+ alist(
989
+ K ~ dnorm( mu , sigma ) ,
990
+ mu <- a + bN*N + bM*M ,
991
+ a ~ dnorm( 0 , 0.2 ) ,
992
+ bN ~ dnorm( 0 , 0.5 ) ,
993
+ bM ~ dnorm( 0 , 0.5 ) ,
994
+ sigma ~ dexp( 1 )
995
+ ) , data=dcc )
996
+ precis(m5.7)
997
+
998
+ ## R code 5.40
999
+ plot( coeftab( m5.5 , m5.6 , m5.7 ) , pars=c("bM","bN") )
1000
+
1001
+ ## R code 5.41
1002
+ xseq <- seq( from=min(dcc$M)-0.15 , to=max(dcc$M)+0.15 , length.out=30 )
1003
+ mu <- link( m5.7 , data=data.frame( M=xseq , N=0 ) )
1004
+ mu_mean <- apply(mu,2,mean)
1005
+ mu_PI <- apply(mu,2,PI)
1006
+ plot( NULL , xlim=range(dcc$M) , ylim=range(dcc$K) )
1007
+ lines( xseq , mu_mean , lwd=2 )
1008
+ shade( mu_PI , xseq )
1009
+
1010
+ ## R code 5.42
1011
+ # M -> K <- N
1012
+ # M -> N
1013
+ n <- 100
1014
+ M <- rnorm( n )
1015
+ N <- rnorm( n , M )
1016
+ K <- rnorm( n , N - M )
1017
+ d_sim <- data.frame(K=K,N=N,M=M)
1018
+
1019
+ ## R code 5.43
1020
+ # M -> K <- N
1021
+ # N -> M
1022
+ n <- 100
1023
+ N <- rnorm( n )
1024
+ M <- rnorm( n , N )
1025
+ K <- rnorm( n , N - M )
1026
+ d_sim2 <- data.frame(K=K,N=N,M=M)
1027
+
1028
+ # M -> K <- N
1029
+ # M <- U -> N
1030
+ n <- 100
1031
+ U <- rnorm( n )
1032
+ N <- rnorm( n , U )
1033
+ M <- rnorm( n , U )
1034
+ K <- rnorm( n , N - M )
1035
+ d_sim3 <- data.frame(K=K,N=N,M=M)
1036
+
1037
+ ## R code 5.44
1038
+ dag5.7 <- dagitty( "dag{
1039
+ M -> K <- N
1040
+ M -> N }" )
1041
+ coordinates(dag5.7) <- list( x=c(M=0,K=1,N=2) , y=c(M=0.5,K=1,N=0.5) )
1042
+ MElist <- equivalentDAGs(dag5.7)
1043
+
1044
+ ## R code 5.45
1045
+ data(Howell1)
1046
+ d <- Howell1
1047
+ str(d)
1048
+
1049
+ ## R code 5.46
1050
+ mu_female <- rnorm(1e4,178,20)
1051
+ mu_male <- rnorm(1e4,178,20) + rnorm(1e4,0,10)
1052
+ precis( data.frame( mu_female , mu_male ) )
1053
+
1054
+ ## R code 5.47
1055
+ d$sex <- ifelse( d$male==1 , 2 , 1 )
1056
+ str( d$sex )
1057
+
1058
+ ## R code 5.48
1059
+ m5.8 <- quap(
1060
+ alist(
1061
+ height ~ dnorm( mu , sigma ) ,
1062
+ mu <- a[sex] ,
1063
+ a[sex] ~ dnorm( 178 , 20 ) ,
1064
+ sigma ~ dunif( 0 , 50 )
1065
+ ) , data=d )
1066
+ precis( m5.8 , depth=2 )
1067
+
1068
+ ## R code 5.49
1069
+ post <- extract.samples(m5.8)
1070
+ post$diff_fm <- post$a[,1] - post$a[,2]
1071
+ precis( post , depth=2 )
1072
+
1073
+ ## R code 5.50
1074
+ data(milk)
1075
+ d <- milk
1076
+ levels(d$clade)
1077
+
1078
+ ## R code 5.51
1079
+ d$clade_id <- as.integer( d$clade )
1080
+
1081
+ ## R code 5.52
1082
+ d$K <- standardize( d$kcal.per.g )
1083
+ m5.9 <- quap(
1084
+ alist(
1085
+ K ~ dnorm( mu , sigma ),
1086
+ mu <- a[clade_id],
1087
+ a[clade_id] ~ dnorm( 0 , 0.5 ),
1088
+ sigma ~ dexp( 1 )
1089
+ ) , data=d )
1090
+ labels <- paste( "a[" , 1:4 , "]:" , levels(d$clade) , sep="" )
1091
+ plot( precis( m5.9 , depth=2 , pars="a" ) , labels=labels ,
1092
+ xlab="expected kcal (std)" )
1093
+
1094
+ ## R code 5.53
1095
+ set.seed(63)
1096
+ d$house <- sample( rep(1:4,each=8) , size=nrow(d) )
1097
+
1098
+ ## R code 5.54
1099
+ m5.10 <- quap(
1100
+ alist(
1101
+ K ~ dnorm( mu , sigma ),
1102
+ mu <- a[clade_id] + h[house],
1103
+ a[clade_id] ~ dnorm( 0 , 0.5 ),
1104
+ h[house] ~ dnorm( 0 , 0.5 ),
1105
+ sigma ~ dexp( 1 )
1106
+ ) , data=d )
1107
+
1108
+ ## R code 6.1
1109
+ set.seed(1914)
1110
+ N <- 200 # num grant proposals
1111
+ p <- 0.1 # proportion to select
1112
+ # uncorrelated newsworthiness and trustworthiness
1113
+ nw <- rnorm(N)
1114
+ tw <- rnorm(N)
1115
+ # select top 10% of combined scores
1116
+ s <- nw + tw # total score
1117
+ q <- quantile( s , 1-p ) # top 10% threshold
1118
+ selected <- ifelse( s >= q , TRUE , FALSE )
1119
+ cor( tw[selected] , nw[selected] )
1120
+
1121
+ ## R code 6.2
1122
+ N <- 100 # number of individuals
1123
+ set.seed(909)
1124
+ height <- rnorm(N,10,2) # sim total height of each
1125
+ leg_prop <- runif(N,0.4,0.5) # leg as proportion of height
1126
+ leg_left <- leg_prop*height + # sim left leg as proportion + error
1127
+ rnorm( N , 0 , 0.02 )
1128
+ leg_right <- leg_prop*height + # sim right leg as proportion + error
1129
+ rnorm( N , 0 , 0.02 )
1130
+ # combine into data frame
1131
+ d <- data.frame(height,leg_left,leg_right)
1132
+
1133
+ ## R code 6.3
1134
+ m6.1 <- quap(
1135
+ alist(
1136
+ height ~ dnorm( mu , sigma ) ,
1137
+ mu <- a + bl*leg_left + br*leg_right ,
1138
+ a ~ dnorm( 10 , 100 ) ,
1139
+ bl ~ dnorm( 2 , 10 ) ,
1140
+ br ~ dnorm( 2 , 10 ) ,
1141
+ sigma ~ dexp( 1 )
1142
+ ) , data=d )
1143
+ precis(m6.1)
1144
+
1145
+ ## R code 6.4
1146
+ plot(precis(m6.1))
1147
+
1148
+ ## R code 6.5
1149
+ post <- extract.samples(m6.1)
1150
+ plot( bl ~ br , post , col=col.alpha(rangi2,0.1) , pch=16 )
1151
+
1152
+ ## R code 6.6
1153
+ sum_blbr <- post$bl + post$br
1154
+ dens( sum_blbr , col=rangi2 , lwd=2 , xlab="sum of bl and br" )
1155
+
1156
+ ## R code 6.7
1157
+ m6.2 <- quap(
1158
+ alist(
1159
+ height ~ dnorm( mu , sigma ) ,
1160
+ mu <- a + bl*leg_left,
1161
+ a ~ dnorm( 10 , 100 ) ,
1162
+ bl ~ dnorm( 2 , 10 ) ,
1163
+ sigma ~ dexp( 1 )
1164
+ ) , data=d )
1165
+ precis(m6.2)
1166
+
1167
+ ## R code 6.8
1168
+ library(rethinking)
1169
+ data(milk)
1170
+ d <- milk
1171
+ d$K <- standardize( d$kcal.per.g )
1172
+ d$F <- standardize( d$perc.fat )
1173
+ d$L <- standardize( d$perc.lactose )
1174
+
1175
+ ## R code 6.9
1176
+ # kcal.per.g regressed on perc.fat
1177
+ m6.3 <- quap(
1178
+ alist(
1179
+ K ~ dnorm( mu , sigma ) ,
1180
+ mu <- a + bF*F ,
1181
+ a ~ dnorm( 0 , 0.2 ) ,
1182
+ bF ~ dnorm( 0 , 0.5 ) ,
1183
+ sigma ~ dexp( 1 )
1184
+ ) , data=d )
1185
+
1186
+ # kcal.per.g regressed on perc.lactose
1187
+ m6.4 <- quap(
1188
+ alist(
1189
+ K ~ dnorm( mu , sigma ) ,
1190
+ mu <- a + bL*L ,
1191
+ a ~ dnorm( 0 , 0.2 ) ,
1192
+ bL ~ dnorm( 0 , 0.5 ) ,
1193
+ sigma ~ dexp( 1 )
1194
+ ) , data=d )
1195
+
1196
+ precis( m6.3 )
1197
+ precis( m6.4 )
1198
+
1199
+ ## R code 6.10
1200
+ m6.5 <- quap(
1201
+ alist(
1202
+ K ~ dnorm( mu , sigma ) ,
1203
+ mu <- a + bF*F + bL*L ,
1204
+ a ~ dnorm( 0 , 0.2 ) ,
1205
+ bF ~ dnorm( 0 , 0.5 ) ,
1206
+ bL ~ dnorm( 0 , 0.5 ) ,
1207
+ sigma ~ dexp( 1 )
1208
+ ) ,
1209
+ data=d )
1210
+ precis( m6.5 )
1211
+
1212
+ ## R code 6.11
1213
+ pairs( ~ kcal.per.g + perc.fat + perc.lactose , data=d , col=rangi2 )
1214
+
1215
+ ## R code 6.12
1216
+ library(rethinking)
1217
+ data(milk)
1218
+ d <- milk
1219
+ sim.coll <- function( r=0.9 ) {
1220
+ d$x <- rnorm( nrow(d) , mean=r*d$perc.fat ,
1221
+ sd=sqrt( (1-r^2)*var(d$perc.fat) ) )
1222
+ m <- lm( kcal.per.g ~ perc.fat + x , data=d )
1223
+ sqrt( diag( vcov(m) ) )[2] # stddev of parameter
1224
+ }
1225
+ rep.sim.coll <- function( r=0.9 , n=100 ) {
1226
+ stddev <- replicate( n , sim.coll(r) )
1227
+ mean(stddev)
1228
+ }
1229
+ r.seq <- seq(from=0,to=0.99,by=0.01)
1230
+ stddev <- sapply( r.seq , function(z) rep.sim.coll(r=z,n=100) )
1231
+ plot( stddev ~ r.seq , type="l" , col=rangi2, lwd=2 , xlab="correlation" )
1232
+
1233
+ ## R code 6.13
1234
+ set.seed(71)
1235
+ # number of plants
1236
+ N <- 100
1237
+
1238
+ # simulate initial heights
1239
+ h0 <- rnorm(N,10,2)
1240
+
1241
+ # assign treatments and simulate fungus and growth
1242
+ treatment <- rep( 0:1 , each=N/2 )
1243
+ fungus <- rbinom( N , size=1 , prob=0.5 - treatment*0.4 )
1244
+ h1 <- h0 + rnorm(N, 5 - 3*fungus)
1245
+
1246
+ # compose a clean data frame
1247
+ d <- data.frame( h0=h0 , h1=h1 , treatment=treatment , fungus=fungus )
1248
+ precis(d)
1249
+
1250
+ ## R code 6.14
1251
+ sim_p <- rlnorm( 1e4 , 0 , 0.25 )
1252
+ precis( data.frame(sim_p) )
1253
+
1254
+ ## R code 6.15
1255
+ m6.6 <- quap(
1256
+ alist(
1257
+ h1 ~ dnorm( mu , sigma ),
1258
+ mu <- h0*p,
1259
+ p ~ dlnorm( 0 , 0.25 ),
1260
+ sigma ~ dexp( 1 )
1261
+ ), data=d )
1262
+ precis(m6.6)
1263
+
1264
+ ## R code 6.16
1265
+ m6.7 <- quap(
1266
+ alist(
1267
+ h1 ~ dnorm( mu , sigma ),
1268
+ mu <- h0 * p,
1269
+ p <- a + bt*treatment + bf*fungus,
1270
+ a ~ dlnorm( 0 , 0.2 ) ,
1271
+ bt ~ dnorm( 0 , 0.5 ),
1272
+ bf ~ dnorm( 0 , 0.5 ),
1273
+ sigma ~ dexp( 1 )
1274
+ ), data=d )
1275
+ precis(m6.7)
1276
+
1277
+ ## R code 6.17
1278
+ m6.8 <- quap(
1279
+ alist(
1280
+ h1 ~ dnorm( mu , sigma ),
1281
+ mu <- h0 * p,
1282
+ p <- a + bt*treatment,
1283
+ a ~ dlnorm( 0 , 0.2 ),
1284
+ bt ~ dnorm( 0 , 0.5 ),
1285
+ sigma ~ dexp( 1 )
1286
+ ), data=d )
1287
+ precis(m6.8)
1288
+
1289
+ ## R code 6.18
1290
+ library(dagitty)
1291
+ plant_dag <- dagitty( "dag {
1292
+ H_0 -> H_1
1293
+ F -> H_1
1294
+ T -> F
1295
+ }")
1296
+ coordinates( plant_dag ) <- list( x=c(H_0=0,T=2,F=1.5,H_1=1) ,
1297
+ y=c(H_0=0,T=0,F=0,H_1=0) )
1298
+ drawdag( plant_dag )
1299
+
1300
+ ## R code 6.19
1301
+ impliedConditionalIndependencies(plant_dag)
1302
+
1303
+ ## R code 6.20
1304
+ set.seed(71)
1305
+ N <- 1000
1306
+ h0 <- rnorm(N,10,2)
1307
+ treatment <- rep( 0:1 , each=N/2 )
1308
+ M <- rbern(N)
1309
+ fungus <- rbinom( N , size=1 , prob=0.5 - treatment*0.4 + 0.4*M )
1310
+ h1 <- h0 + rnorm( N , 5 + 3*M )
1311
+ d2 <- data.frame( h0=h0 , h1=h1 , treatment=treatment , fungus=fungus )
1312
+
1313
+ ## R code 6.21
1314
+ library(rethinking)
1315
+ d <- sim_happiness( seed=1977 , N_years=1000 )
1316
+ precis(d)
1317
+
1318
+ ## R code 6.22
1319
+ d2 <- d[ d$age>17 , ] # only adults
1320
+ d2$A <- ( d2$age - 18 ) / ( 65 - 18 )
1321
+
1322
+ ## R code 6.23
1323
+ d2$mid <- d2$married + 1
1324
+ m6.9 <- quap(
1325
+ alist(
1326
+ happiness ~ dnorm( mu , sigma ),
1327
+ mu <- a[mid] + bA*A,
1328
+ a[mid] ~ dnorm( 0 , 1 ),
1329
+ bA ~ dnorm( 0 , 2 ),
1330
+ sigma ~ dexp(1)
1331
+ ) , data=d2 )
1332
+ precis(m6.9,depth=2)
1333
+
1334
+ ## R code 6.24
1335
+ m6.10 <- quap(
1336
+ alist(
1337
+ happiness ~ dnorm( mu , sigma ),
1338
+ mu <- a + bA*A,
1339
+ a ~ dnorm( 0 , 1 ),
1340
+ bA ~ dnorm( 0 , 2 ),
1341
+ sigma ~ dexp(1)
1342
+ ) , data=d2 )
1343
+ precis(m6.10)
1344
+
1345
+ ## R code 6.25
1346
+ N <- 200 # number of grandparent-parent-child triads
1347
+ b_GP <- 1 # direct effect of G on P
1348
+ b_GC <- 0 # direct effect of G on C
1349
+ b_PC <- 1 # direct effect of P on C
1350
+ b_U <- 2 # direct effect of U on P and C
1351
+
1352
+ ## R code 6.26
1353
+ set.seed(1)
1354
+ U <- 2*rbern( N , 0.5 ) - 1
1355
+ G <- rnorm( N )
1356
+ P <- rnorm( N , b_GP*G + b_U*U )
1357
+ C <- rnorm( N , b_PC*P + b_GC*G + b_U*U )
1358
+ d <- data.frame( C=C , P=P , G=G , U=U )
1359
+
1360
+ ## R code 6.27
1361
+ m6.11 <- quap(
1362
+ alist(
1363
+ C ~ dnorm( mu , sigma ),
1364
+ mu <- a + b_PC*P + b_GC*G,
1365
+ a ~ dnorm( 0 , 1 ),
1366
+ c(b_PC,b_GC) ~ dnorm( 0 , 1 ),
1367
+ sigma ~ dexp( 1 )
1368
+ ), data=d )
1369
+ precis(m6.11)
1370
+
1371
+ ## R code 6.28
1372
+ m6.12 <- quap(
1373
+ alist(
1374
+ C ~ dnorm( mu , sigma ),
1375
+ mu <- a + b_PC*P + b_GC*G + b_U*U,
1376
+ a ~ dnorm( 0 , 1 ),
1377
+ c(b_PC,b_GC,b_U) ~ dnorm( 0 , 1 ),
1378
+ sigma ~ dexp( 1 )
1379
+ ), data=d )
1380
+ precis(m6.12)
1381
+
1382
+ ## R code 6.29
1383
+ library(dagitty)
1384
+ dag_6.1 <- dagitty( "dag {
1385
+ U [unobserved]
1386
+ X -> Y
1387
+ X <- U <- A -> C -> Y
1388
+ U -> B <- C
1389
+ }")
1390
+ adjustmentSets( dag_6.1 , exposure="X" , outcome="Y" )
1391
+
1392
+ ## R code 6.30
1393
+ library(dagitty)
1394
+ dag_6.2 <- dagitty( "dag {
1395
+ A -> D
1396
+ A -> M -> D
1397
+ A <- S -> M
1398
+ S -> W -> D
1399
+ }")
1400
+ adjustmentSets( dag_6.2 , exposure="W" , outcome="D" )
1401
+
1402
+ ## R code 6.31
1403
+ impliedConditionalIndependencies( dag_6.2 )
1404
+
1405
+ ## R code 7.1
1406
+ sppnames <- c( "afarensis","africanus","habilis","boisei",
1407
+ "rudolfensis","ergaster","sapiens")
1408
+ brainvolcc <- c( 438 , 452 , 612, 521, 752, 871, 1350 )
1409
+ masskg <- c( 37.0 , 35.5 , 34.5 , 41.5 , 55.5 , 61.0 , 53.5 )
1410
+ d <- data.frame( species=sppnames , brain=brainvolcc , mass=masskg )
1411
+
1412
+ ## R code 7.2
1413
+ d$mass_std <- (d$mass - mean(d$mass))/sd(d$mass)
1414
+ d$brain_std <- d$brain / max(d$brain)
1415
+
1416
+ ## R code 7.3
1417
+ m7.1 <- quap(
1418
+ alist(
1419
+ brain_std ~ dnorm( mu , exp(log_sigma) ),
1420
+ mu <- a + b*mass_std,
1421
+ a ~ dnorm( 0.5 , 1 ),
1422
+ b ~ dnorm( 0 , 10 ),
1423
+ log_sigma ~ dnorm( 0 , 1 )
1424
+ ), data=d )
1425
+
1426
+ ## R code 7.4
1427
+ m7.1_OLS <- lm( brain_std ~ mass_std , data=d )
1428
+ post <- extract.samples( m7.1_OLS )
1429
+
1430
+ ## R code 7.5
1431
+ set.seed(12)
1432
+ s <- sim( m7.1 )
1433
+ r <- apply(s,2,mean) - d$brain_std
1434
+ resid_var <- var2(r)
1435
+ outcome_var <- var2( d$brain_std )
1436
+ 1 - resid_var/outcome_var
1437
+
1438
+ ## R code 7.6
1439
+ R2_is_bad <- function( quap_fit ) {
1440
+ s <- sim( quap_fit , refresh=0 )
1441
+ r <- apply(s,2,mean) - d$brain_std
1442
+ 1 - var2(r)/var2(d$brain_std)
1443
+ }
1444
+
1445
+ ## R code 7.7
1446
+ m7.2 <- quap(
1447
+ alist(
1448
+ brain_std ~ dnorm( mu , exp(log_sigma) ),
1449
+ mu <- a + b[1]*mass_std + b[2]*mass_std^2,
1450
+ a ~ dnorm( 0.5 , 1 ),
1451
+ b ~ dnorm( 0 , 10 ),
1452
+ log_sigma ~ dnorm( 0 , 1 )
1453
+ ), data=d , start=list(b=rep(0,2)) )
1454
+
1455
+ ## R code 7.8
1456
+ m7.3 <- quap(
1457
+ alist(
1458
+ brain_std ~ dnorm( mu , exp(log_sigma) ),
1459
+ mu <- a + b[1]*mass_std + b[2]*mass_std^2 +
1460
+ b[3]*mass_std^3,
1461
+ a ~ dnorm( 0.5 , 1 ),
1462
+ b ~ dnorm( 0 , 10 ),
1463
+ log_sigma ~ dnorm( 0 , 1 )
1464
+ ), data=d , start=list(b=rep(0,3)) )
1465
+
1466
+ m7.4 <- quap(
1467
+ alist(
1468
+ brain_std ~ dnorm( mu , exp(log_sigma) ),
1469
+ mu <- a + b[1]*mass_std + b[2]*mass_std^2 +
1470
+ b[3]*mass_std^3 + b[4]*mass_std^4,
1471
+ a ~ dnorm( 0.5 , 1 ),
1472
+ b ~ dnorm( 0 , 10 ),
1473
+ log_sigma ~ dnorm( 0 , 1 )
1474
+ ), data=d , start=list(b=rep(0,4)) )
1475
+
1476
+ m7.5 <- quap(
1477
+ alist(
1478
+ brain_std ~ dnorm( mu , exp(log_sigma) ),
1479
+ mu <- a + b[1]*mass_std + b[2]*mass_std^2 +
1480
+ b[3]*mass_std^3 + b[4]*mass_std^4 +
1481
+ b[5]*mass_std^5,
1482
+ a ~ dnorm( 0.5 , 1 ),
1483
+ b ~ dnorm( 0 , 10 ),
1484
+ log_sigma ~ dnorm( 0 , 1 )
1485
+ ), data=d , start=list(b=rep(0,5)) )
1486
+
1487
+ ## R code 7.9
1488
+ m7.6 <- quap(
1489
+ alist(
1490
+ brain_std ~ dnorm( mu , 0.001 ),
1491
+ mu <- a + b[1]*mass_std + b[2]*mass_std^2 +
1492
+ b[3]*mass_std^3 + b[4]*mass_std^4 +
1493
+ b[5]*mass_std^5 + b[6]*mass_std^6,
1494
+ a ~ dnorm( 0.5 , 1 ),
1495
+ b ~ dnorm( 0 , 10 )
1496
+ ), data=d , start=list(b=rep(0,6)) )
1497
+
1498
+ ## R code 7.10
1499
+ post <- extract.samples(m7.1)
1500
+ mass_seq <- seq( from=min(d$mass_std) , to=max(d$mass_std) , length.out=100 )
1501
+ l <- link( m7.1 , data=list( mass_std=mass_seq ) )
1502
+ mu <- apply( l , 2 , mean )
1503
+ ci <- apply( l , 2 , PI )
1504
+ plot( brain_std ~ mass_std , data=d )
1505
+ lines( mass_seq , mu )
1506
+ shade( ci , mass_seq )
1507
+
1508
+ ## R code 7.11
1509
+ d_minus_i <- d[ -i , ]
1510
+
1511
+ ## R code 7.12
1512
+ p <- c( 0.3 , 0.7 )
1513
+ -sum( p*log(p) )
1514
+
1515
+ ## R code 7.13
1516
+ set.seed(1)
1517
+ lppd( m7.1 , n=1e4 )
1518
+
1519
+ ## R code 7.14
1520
+ set.seed(1)
1521
+ logprob <- sim( m7.1 , ll=TRUE , n=1e4 )
1522
+ n <- ncol(logprob)
1523
+ ns <- nrow(logprob)
1524
+ f <- function( i ) log_sum_exp( logprob[,i] ) - log(ns)
1525
+ ( lppd <- sapply( 1:n , f ) )
1526
+
1527
+ ## R code 7.15
1528
+ set.seed(1)
1529
+ sapply( list(m7.1,m7.2,m7.3,m7.4,m7.5,m7.6) , function(m) sum(lppd(m)) )
1530
+
1531
+ ## R code 7.16
1532
+ N <- 20
1533
+ kseq <- 1:5
1534
+ dev <- sapply( kseq , function(k) {
1535
+ print(k);
1536
+ r <- replicate( 1e4 , sim_train_test( N=N, k=k ) );
1537
+ c( mean(r[1,]) , mean(r[2,]) , sd(r[1,]) , sd(r[2,]) )
1538
+ } )
1539
+
1540
+ ## R code 7.17
1541
+ r <- mcreplicate( 1e4 , sim_train_test( N=N, k=k ) , mc.cores=4 )
1542
+
1543
+ ## R code 7.18
1544
+ plot( 1:5 , dev[1,] , ylim=c( min(dev[1:2,])-5 , max(dev[1:2,])+10 ) ,
1545
+ xlim=c(1,5.1) , xlab="number of parameters" , ylab="deviance" ,
1546
+ pch=16 , col=rangi2 )
1547
+ mtext( concat( "N = ",N ) )
1548
+ points( (1:5)+0.1 , dev[2,] )
1549
+ for ( i in kseq ) {
1550
+ pts_in <- dev[1,i] + c(-1,+1)*dev[3,i]
1551
+ pts_out <- dev[2,i] + c(-1,+1)*dev[4,i]
1552
+ lines( c(i,i) , pts_in , col=rangi2 )
1553
+ lines( c(i,i)+0.1 , pts_out )
1554
+ }
1555
+
1556
+ ## R code 7.19
1557
+ data(cars)
1558
+ m <- quap(
1559
+ alist(
1560
+ dist ~ dnorm(mu,sigma),
1561
+ mu <- a + b*speed,
1562
+ a ~ dnorm(0,100),
1563
+ b ~ dnorm(0,10),
1564
+ sigma ~ dexp(1)
1565
+ ) , data=cars )
1566
+ set.seed(94)
1567
+ post <- extract.samples(m,n=1000)
1568
+
1569
+ ## R code 7.20
1570
+ n_samples <- 1000
1571
+ logprob <- sapply( 1:n_samples ,
1572
+ function(s) {
1573
+ mu <- post$a[s] + post$b[s]*cars$speed
1574
+ dnorm( cars$dist , mu , post$sigma[s] , log=TRUE )
1575
+ } )
1576
+
1577
+ ## R code 7.21
1578
+ n_cases <- nrow(cars)
1579
+ lppd <- sapply( 1:n_cases , function(i) log_sum_exp(logprob[i,]) - log(n_samples) )
1580
+
1581
+ ## R code 7.22
1582
+ pWAIC <- sapply( 1:n_cases , function(i) var(logprob[i,]) )
1583
+
1584
+ ## R code 7.23
1585
+ -2*( sum(lppd) - sum(pWAIC) )
1586
+
1587
+ ## R code 7.24
1588
+ waic_vec <- -2*( lppd - pWAIC )
1589
+ sqrt( n_cases*var(waic_vec) )
1590
+
1591
+ ## R code 7.25
1592
+ set.seed(11)
1593
+ WAIC( m6.7 )
1594
+
1595
+ ## R code 7.26
1596
+ set.seed(77)
1597
+ compare( m6.6 , m6.7 , m6.8 , func=WAIC )
1598
+
1599
+ ## R code 7.27
1600
+ set.seed(91)
1601
+ waic_m6.7 <- WAIC( m6.7 , pointwise=TRUE )$WAIC
1602
+ waic_m6.8 <- WAIC( m6.8 , pointwise=TRUE )$WAIC
1603
+ n <- length(waic_m6.7)
1604
+ diff_m6.7_m6.8 <- waic_m6.7 - waic_m6.8
1605
+ sqrt( n*var( diff_m6.7_m6.8 ) )
1606
+
1607
+ ## R code 7.28
1608
+ 40.0 + c(-1,1)*10.4*2.6
1609
+
1610
+ ## R code 7.29
1611
+ plot( compare( m6.6 , m6.7 , m6.8 ) )
1612
+
1613
+ ## R code 7.30
1614
+ set.seed(92)
1615
+ waic_m6.6 <- WAIC( m6.6 , pointwise=TRUE )$WAIC
1616
+ diff_m6.6_m6.8 <- waic_m6.6 - waic_m6.8
1617
+ sqrt( n*var( diff_m6.6_m6.8 ) )
1618
+
1619
+ ## R code 7.31
1620
+ set.seed(93)
1621
+ compare( m6.6 , m6.7 , m6.8 )@dSE
1622
+
1623
+ ## R code 7.32
1624
+ library(rethinking)
1625
+ data(WaffleDivorce)
1626
+ d <- WaffleDivorce
1627
+ d$A <- standardize( d$MedianAgeMarriage )
1628
+ d$D <- standardize( d$Divorce )
1629
+ d$M <- standardize( d$Marriage )
1630
+
1631
+ m5.1 <- quap(
1632
+ alist(
1633
+ D ~ dnorm( mu , sigma ) ,
1634
+ mu <- a + bA * A ,
1635
+ a ~ dnorm( 0 , 0.2 ) ,
1636
+ bA ~ dnorm( 0 , 0.5 ) ,
1637
+ sigma ~ dexp( 1 )
1638
+ ) , data = d )
1639
+
1640
+ m5.2 <- quap(
1641
+ alist(
1642
+ D ~ dnorm( mu , sigma ) ,
1643
+ mu <- a + bM * M ,
1644
+ a ~ dnorm( 0 , 0.2 ) ,
1645
+ bM ~ dnorm( 0 , 0.5 ) ,
1646
+ sigma ~ dexp( 1 )
1647
+ ) , data = d )
1648
+
1649
+ m5.3 <- quap(
1650
+ alist(
1651
+ D ~ dnorm( mu , sigma ) ,
1652
+ mu <- a + bM*M + bA*A ,
1653
+ a ~ dnorm( 0 , 0.2 ) ,
1654
+ bM ~ dnorm( 0 , 0.5 ) ,
1655
+ bA ~ dnorm( 0 , 0.5 ) ,
1656
+ sigma ~ dexp( 1 )
1657
+ ) , data = d )
1658
+
1659
+ ## R code 7.33
1660
+ set.seed(24071847)
1661
+ compare( m5.1 , m5.2 , m5.3 , func=PSIS )
1662
+
1663
+ ## R code 7.34
1664
+ set.seed(24071847)
1665
+ PSIS_m5.3 <- PSIS(m5.3,pointwise=TRUE)
1666
+ set.seed(24071847)
1667
+ WAIC_m5.3 <- WAIC(m5.3,pointwise=TRUE)
1668
+ plot( PSIS_m5.3$k , WAIC_m5.3$penalty , xlab="PSIS Pareto k" ,
1669
+ ylab="WAIC penalty" , col=rangi2 , lwd=2 )
1670
+
1671
+ ## R code 7.35
1672
+ m5.3t <- quap(
1673
+ alist(
1674
+ D ~ dstudent( 2 , mu , sigma ) ,
1675
+ mu <- a + bM*M + bA*A ,
1676
+ a ~ dnorm( 0 , 0.2 ) ,
1677
+ bM ~ dnorm( 0 , 0.5 ) ,
1678
+ bA ~ dnorm( 0 , 0.5 ) ,
1679
+ sigma ~ dexp( 1 )
1680
+ ) , data = d )
1681
+
1682
+ ## R code 8.1
1683
+ library(rethinking)
1684
+ data(rugged)
1685
+ d <- rugged
1686
+
1687
+ # make log version of outcome
1688
+ d$log_gdp <- log( d$rgdppc_2000 )
1689
+
1690
+ # extract countries with GDP data
1691
+ dd <- d[ complete.cases(d$rgdppc_2000) , ]
1692
+
1693
+ # rescale variables
1694
+ dd$log_gdp_std <- dd$log_gdp / mean(dd$log_gdp)
1695
+ dd$rugged_std <- dd$rugged / max(dd$rugged)
1696
+
1697
+ ## R code 8.2
1698
+ m8.1 <- quap(
1699
+ alist(
1700
+ log_gdp_std ~ dnorm( mu , sigma ) ,
1701
+ mu <- a + b*( rugged_std - 0.215 ) ,
1702
+ a ~ dnorm( 1 , 1 ) ,
1703
+ b ~ dnorm( 0 , 1 ) ,
1704
+ sigma ~ dexp( 1 )
1705
+ ) , data=dd )
1706
+
1707
+ ## R code 8.3
1708
+ set.seed(7)
1709
+ prior <- extract.prior( m8.1 )
1710
+
1711
+ # set up the plot dimensions
1712
+ plot( NULL , xlim=c(0,1) , ylim=c(0.5,1.5) ,
1713
+ xlab="ruggedness" , ylab="log GDP" )
1714
+ abline( h=min(dd$log_gdp_std) , lty=2 )
1715
+ abline( h=max(dd$log_gdp_std) , lty=2 )
1716
+
1717
+ # draw 50 lines from the prior
1718
+ rugged_seq <- seq( from=-0.1 , to=1.1 , length.out=30 )
1719
+ mu <- link( m8.1 , post=prior , data=data.frame(rugged_std=rugged_seq) )
1720
+ for ( i in 1:50 ) lines( rugged_seq , mu[i,] , col=col.alpha("black",0.3) )
1721
+
1722
+ ## R code 8.4
1723
+ sum( abs(prior$b) > 0.6 ) / length(prior$b)
1724
+
1725
+ ## R code 8.5
1726
+ m8.1 <- quap(
1727
+ alist(
1728
+ log_gdp_std ~ dnorm( mu , sigma ) ,
1729
+ mu <- a + b*( rugged_std - 0.215 ) ,
1730
+ a ~ dnorm( 1 , 0.1 ) ,
1731
+ b ~ dnorm( 0 , 0.3 ) ,
1732
+ sigma ~ dexp(1)
1733
+ ) , data=dd )
1734
+
1735
+ ## R code 8.6
1736
+ precis( m8.1 )
1737
+
1738
+ ## R code 8.7
1739
+ # make variable to index Africa (1) or not (2)
1740
+ dd$cid <- ifelse( dd$cont_africa==1 , 1 , 2 )
1741
+
1742
+ ## R code 8.8
1743
+ m8.2 <- quap(
1744
+ alist(
1745
+ log_gdp_std ~ dnorm( mu , sigma ) ,
1746
+ mu <- a[cid] + b*( rugged_std - 0.215 ) ,
1747
+ a[cid] ~ dnorm( 1 , 0.1 ) ,
1748
+ b ~ dnorm( 0 , 0.3 ) ,
1749
+ sigma ~ dexp( 1 )
1750
+ ) , data=dd )
1751
+
1752
+ ## R code 8.9
1753
+ compare( m8.1 , m8.2 )
1754
+
1755
+ ## R code 8.10
1756
+ precis( m8.2 , depth=2 )
1757
+
1758
+ ## R code 8.11
1759
+ post <- extract.samples(m8.2)
1760
+ diff_a1_a2 <- post$a[,1] - post$a[,2]
1761
+ PI( diff_a1_a2 )
1762
+
1763
+ ## R code 8.12
1764
+ rugged.seq <- seq( from=-0.1 , to=1.1 , length.out=30 )
1765
+ # compute mu over samples, fixing cid=2 and then cid=1
1766
+ mu.NotAfrica <- link( m8.2 ,
1767
+ data=data.frame( cid=2 , rugged_std=rugged.seq ) )
1768
+ mu.Africa <- link( m8.2 ,
1769
+ data=data.frame( cid=1 , rugged_std=rugged.seq ) )
1770
+ # summarize to means and intervals
1771
+ mu.NotAfrica_mu <- apply( mu.NotAfrica , 2 , mean )
1772
+ mu.NotAfrica_ci <- apply( mu.NotAfrica , 2 , PI , prob=0.97 )
1773
+ mu.Africa_mu <- apply( mu.Africa , 2 , mean )
1774
+ mu.Africa_ci <- apply( mu.Africa , 2 , PI , prob=0.97 )
1775
+
1776
+ ## R code 8.13
1777
+ m8.3 <- quap(
1778
+ alist(
1779
+ log_gdp_std ~ dnorm( mu , sigma ) ,
1780
+ mu <- a[cid] + b[cid]*( rugged_std - 0.215 ) ,
1781
+ a[cid] ~ dnorm( 1 , 0.1 ) ,
1782
+ b[cid] ~ dnorm( 0 , 0.3 ) ,
1783
+ sigma ~ dexp( 1 )
1784
+ ) , data=dd )
1785
+
1786
+ ## R code 8.14
1787
+ precis( m8.5 , depth=2 )
1788
+
1789
+ ## R code 8.15
1790
+ compare( m8.1 , m8.2 , m8.3 , func=PSIS )
1791
+
1792
+ ## R code 8.16
1793
+ plot( PSIS( m8.3 , pointwise=TRUE )$k )
1794
+
1795
+ ## R code 8.17
1796
+ # plot Africa - cid=1
1797
+ d.A1 <- dd[ dd$cid==1 , ]
1798
+ plot( d.A1$rugged_std , d.A1$log_gdp_std , pch=16 , col=rangi2 ,
1799
+ xlab="ruggedness (standardized)" , ylab="log GDP (as proportion of mean)" ,
1800
+ xlim=c(0,1) )
1801
+ mu <- link( m8.3 , data=data.frame( cid=1 , rugged_std=rugged_seq ) )
1802
+ mu_mean <- apply( mu , 2 , mean )
1803
+ mu_ci <- apply( mu , 2 , PI , prob=0.97 )
1804
+ lines( rugged_seq , mu_mean , lwd=2 )
1805
+ shade( mu_ci , rugged_seq , col=col.alpha(rangi2,0.3) )
1806
+ mtext("African nations")
1807
+
1808
+ # plot non-Africa - cid=2
1809
+ d.A0 <- dd[ dd$cid==2 , ]
1810
+ plot( d.A0$rugged_std , d.A0$log_gdp_std , pch=1 , col="black" ,
1811
+ xlab="ruggedness (standardized)" , ylab="log GDP (as proportion of mean)" ,
1812
+ xlim=c(0,1) )
1813
+ mu <- link( m8.3 , data=data.frame( cid=2 , rugged_std=rugged_seq ) )
1814
+ mu_mean <- apply( mu , 2 , mean )
1815
+ mu_ci <- apply( mu , 2 , PI , prob=0.97 )
1816
+ lines( rugged_seq , mu_mean , lwd=2 )
1817
+ shade( mu_ci , rugged_seq )
1818
+ mtext("Non-African nations")
1819
+
1820
+ ## R code 8.18
1821
+ rugged_seq <- seq(from=-0.2,to=1.2,length.out=30)
1822
+ muA <- link( m8.3 , data=data.frame(cid=1,rugged_std=rugged_seq) )
1823
+ muN <- link( m8.3 , data=data.frame(cid=2,rugged_std=rugged_seq) )
1824
+ delta <- muA - muN
1825
+
1826
+ ## R code 8.19
1827
+ library(rethinking)
1828
+ data(tulips)
1829
+ d <- tulips
1830
+ str(d)
1831
+
1832
+ ## R code 8.20
1833
+ d$blooms_std <- d$blooms / max(d$blooms)
1834
+ d$water_cent <- d$water - mean(d$water)
1835
+ d$shade_cent <- d$shade - mean(d$shade)
1836
+
1837
+ ## R code 8.21
1838
+ a <- rnorm( 1e4 , 0.5 , 1 ); sum( a < 0 | a > 1 ) / length( a )
1839
+
1840
+ ## R code 8.22
1841
+ a <- rnorm( 1e4 , 0.5 , 0.25 ); sum( a < 0 | a > 1 ) / length( a )
1842
+
1843
+ ## R code 8.23
1844
+ m8.4 <- quap(
1845
+ alist(
1846
+ blooms_std ~ dnorm( mu , sigma ) ,
1847
+ mu <- a + bw*water_cent + bs*shade_cent ,
1848
+ a ~ dnorm( 0.5 , 0.25 ) ,
1849
+ bw ~ dnorm( 0 , 0.25 ) ,
1850
+ bs ~ dnorm( 0 , 0.25 ) ,
1851
+ sigma ~ dexp( 1 )
1852
+ ) , data=d )
1853
+
1854
+ ## R code 8.24
1855
+ m8.5 <- quap(
1856
+ alist(
1857
+ blooms_std ~ dnorm( mu , sigma ) ,
1858
+ mu <- a + bw*water_cent + bs*shade_cent + bws*water_cent*shade_cent ,
1859
+ a ~ dnorm( 0.5 , 0.25 ) ,
1860
+ bw ~ dnorm( 0 , 0.25 ) ,
1861
+ bs ~ dnorm( 0 , 0.25 ) ,
1862
+ bws ~ dnorm( 0 , 0.25 ) ,
1863
+ sigma ~ dexp( 1 )
1864
+ ) , data=d )
1865
+
1866
+ ## R code 8.25
1867
+ par(mfrow=c(1,3)) # 3 plots in 1 row
1868
+ for ( s in -1:1 ) {
1869
+ idx <- which( d$shade_cent==s )
1870
+ plot( d$water_cent[idx] , d$blooms_std[idx] , xlim=c(-1,1) , ylim=c(0,1) ,
1871
+ xlab="water" , ylab="blooms" , pch=16 , col=rangi2 )
1872
+ mu <- link( m8.4 , data=data.frame( shade_cent=s , water_cent=-1:1 ) )
1873
+ for ( i in 1:20 ) lines( -1:1 , mu[i,] , col=col.alpha("black",0.3) )
1874
+ }
1875
+
1876
+ ## R code 8.26
1877
+ set.seed(7)
1878
+ prior <- extract.prior(m8.5)
1879
+
1880
+ ## R code 8.27
1881
+ d$lang.per.cap <- d$num.lang / d$k.pop
1882
+
1883
+ ## R code 9.1
1884
+ num_weeks <- 1e5
1885
+ positions <- rep(0,num_weeks)
1886
+ current <- 10
1887
+ for ( i in 1:num_weeks ) {
1888
+ ## record current position
1889
+ positions[i] <- current
1890
+ ## flip coin to generate proposal
1891
+ proposal <- current + sample( c(-1,1) , size=1 )
1892
+ ## now make sure he loops around the archipelago
1893
+ if ( proposal < 1 ) proposal <- 10
1894
+ if ( proposal > 10 ) proposal <- 1
1895
+ ## move?
1896
+ prob_move <- proposal/current
1897
+ current <- ifelse( runif(1) < prob_move , proposal , current )
1898
+ }
1899
+
1900
+ ## R code 9.2
1901
+ plot( 1:100 , positions[1:100] )
1902
+
1903
+ ## R code 9.3
1904
+ plot( table( positions ) )
1905
+
1906
+ ## R code 9.4
1907
+ D <- 10
1908
+ T <- 1e3
1909
+ Y <- rmvnorm(T,rep(0,D),diag(D))
1910
+ rad_dist <- function( Y ) sqrt( sum(Y^2) )
1911
+ Rd <- sapply( 1:T , function(i) rad_dist( Y[i,] ) )
1912
+ dens( Rd )
1913
+
1914
+ ## R code 9.5
1915
+ # U needs to return neg-log-probability
1916
+ U <- function( q , a=0 , b=1 , k=0 , d=1 ) {
1917
+ muy <- q[1]
1918
+ mux <- q[2]
1919
+ U <- sum( dnorm(y,muy,1,log=TRUE) ) + sum( dnorm(x,mux,1,log=TRUE) ) +
1920
+ dnorm(muy,a,b,log=TRUE) + dnorm(mux,k,d,log=TRUE)
1921
+ return( -U )
1922
+ }
1923
+
1924
+ ## R code 9.6
1925
+ # gradient function
1926
+ # need vector of partial derivatives of U with respect to vector q
1927
+ U_gradient <- function( q , a=0 , b=1 , k=0 , d=1 ) {
1928
+ muy <- q[1]
1929
+ mux <- q[2]
1930
+ G1 <- sum( y - muy ) + (a - muy)/b^2 #dU/dmuy
1931
+ G2 <- sum( x - mux ) + (k - mux)/d^2 #dU/dmux
1932
+ return( c( -G1 , -G2 ) ) # negative bc energy is neg-log-prob
1933
+ }
1934
+ # test data
1935
+ set.seed(7)
1936
+ y <- rnorm(50)
1937
+ x <- rnorm(50)
1938
+ x <- as.numeric(scale(x))
1939
+ y <- as.numeric(scale(y))
1940
+
1941
+ ## R code 9.7
1942
+ library(shape) # for fancy arrows
1943
+ Q <- list()
1944
+ Q$q <- c(-0.1,0.2)
1945
+ pr <- 0.3
1946
+ plot( NULL , ylab="muy" , xlab="mux" , xlim=c(-pr,pr) , ylim=c(-pr,pr) )
1947
+ step <- 0.03
1948
+ L <- 11 # 0.03/28 for U-turns --- 11 for working example
1949
+ n_samples <- 4
1950
+ path_col <- col.alpha("black",0.5)
1951
+ points( Q$q[1] , Q$q[2] , pch=4 , col="black" )
1952
+ for ( i in 1:n_samples ) {
1953
+ Q <- HMC2( U , U_gradient , step , L , Q$q )
1954
+ if ( n_samples < 10 ) {
1955
+ for ( j in 1:L ) {
1956
+ K0 <- sum(Q$ptraj[j,]^2)/2 # kinetic energy
1957
+ lines( Q$traj[j:(j+1),1] , Q$traj[j:(j+1),2] , col=path_col , lwd=1+2*K0 )
1958
+ }
1959
+ points( Q$traj[1:L+1,] , pch=16 , col="white" , cex=0.35 )
1960
+ Arrows( Q$traj[L,1] , Q$traj[L,2] , Q$traj[L+1,1] , Q$traj[L+1,2] ,
1961
+ arr.length=0.35 , arr.adj = 0.7 )
1962
+ text( Q$traj[L+1,1] , Q$traj[L+1,2] , i , cex=0.8 , pos=4 , offset=0.4 )
1963
+ }
1964
+ points( Q$traj[L+1,1] , Q$traj[L+1,2] , pch=ifelse( Q$accept==1 , 16 , 1 ) ,
1965
+ col=ifelse( abs(Q$dH)>0.1 , "red" , "black" ) )
1966
+ }
1967
+
1968
+ ## R code 9.8
1969
+ HMC2 <- function (U, grad_U, epsilon, L, current_q) {
1970
+ q = current_q
1971
+ p = rnorm(length(q),0,1) # random flick - p is momentum.
1972
+ current_p = p
1973
+ # Make a half step for momentum at the beginning
1974
+ p = p - epsilon * grad_U(q) / 2
1975
+ # initialize bookkeeping - saves trajectory
1976
+ qtraj <- matrix(NA,nrow=L+1,ncol=length(q))
1977
+ ptraj <- qtraj
1978
+ qtraj[1,] <- current_q
1979
+ ptraj[1,] <- p
1980
+
1981
+ ## R code 9.9
1982
+ # Alternate full steps for position and momentum
1983
+ for ( i in 1:L ) {
1984
+ q = q + epsilon * p # Full step for the position
1985
+ # Make a full step for the momentum, except at end of trajectory
1986
+ if ( i!=L ) {
1987
+ p = p - epsilon * grad_U(q)
1988
+ ptraj[i+1,] <- p
1989
+ }
1990
+ qtraj[i+1,] <- q
1991
+ }
1992
+
1993
+ ## R code 9.10
1994
+ # Make a half step for momentum at the end
1995
+ p = p - epsilon * grad_U(q) / 2
1996
+ ptraj[L+1,] <- p
1997
+ # Negate momentum at end of trajectory to make the proposal symmetric
1998
+ p = -p
1999
+ # Evaluate potential and kinetic energies at start and end of trajectory
2000
+ current_U = U(current_q)
2001
+ current_K = sum(current_p^2) / 2
2002
+ proposed_U = U(q)
2003
+ proposed_K = sum(p^2) / 2
2004
+ # Accept or reject the state at end of trajectory, returning either
2005
+ # the position at the end of the trajectory or the initial position
2006
+ accept <- 0
2007
+ if (runif(1) < exp(current_U-proposed_U+current_K-proposed_K)) {
2008
+ new_q <- q # accept
2009
+ accept <- 1
2010
+ } else new_q <- current_q # reject
2011
+ return(list( q=new_q, traj=qtraj, ptraj=ptraj, accept=accept ))
2012
+ }
2013
+
2014
+ ## R code 9.11
2015
+ library(rethinking)
2016
+ data(rugged)
2017
+ d <- rugged
2018
+ d$log_gdp <- log(d$rgdppc_2000)
2019
+ dd <- d[ complete.cases(d$rgdppc_2000) , ]
2020
+ dd$log_gdp_std <- dd$log_gdp / mean(dd$log_gdp)
2021
+ dd$rugged_std <- dd$rugged / max(dd$rugged)
2022
+ dd$cid <- ifelse( dd$cont_africa==1 , 1 , 2 )
2023
+
2024
+ ## R code 9.12
2025
+ m8.3 <- quap(
2026
+ alist(
2027
+ log_gdp_std ~ dnorm( mu , sigma ) ,
2028
+ mu <- a[cid] + b[cid]*( rugged_std - 0.215 ) ,
2029
+ a[cid] ~ dnorm( 1 , 0.1 ) ,
2030
+ b[cid] ~ dnorm( 0 , 0.3 ) ,
2031
+ sigma ~ dexp( 1 )
2032
+ ) , data=dd )
2033
+ precis( m8.3 , depth=2 )
2034
+
2035
+ ## R code 9.13
2036
+ dat_slim <- list(
2037
+ log_gdp_std = dd$log_gdp_std,
2038
+ rugged_std = dd$rugged_std,
2039
+ cid = as.integer( dd$cid )
2040
+ )
2041
+ str(dat_slim)
2042
+
2043
+ ## R code 9.14
2044
+ m9.1 <- ulam(
2045
+ alist(
2046
+ log_gdp_std ~ dnorm( mu , sigma ) ,
2047
+ mu <- a[cid] + b[cid]*( rugged_std - 0.215 ) ,
2048
+ a[cid] ~ dnorm( 1 , 0.1 ) ,
2049
+ b[cid] ~ dnorm( 0 , 0.3 ) ,
2050
+ sigma ~ dexp( 1 )
2051
+ ) , data=dat_slim , chains=1 )
2052
+
2053
+ ## R code 9.15
2054
+ precis( m9.1 , depth=2 )
2055
+
2056
+ ## R code 9.16
2057
+ m9.1 <- ulam(
2058
+ alist(
2059
+ log_gdp_std ~ dnorm( mu , sigma ) ,
2060
+ mu <- a[cid] + b[cid]*( rugged_std - 0.215 ) ,
2061
+ a[cid] ~ dnorm( 1 , 0.1 ) ,
2062
+ b[cid] ~ dnorm( 0 , 0.3 ) ,
2063
+ sigma ~ dexp( 1 )
2064
+ ) , data=dat_slim , chains=4 , cores=4 )
2065
+
2066
+ ## R code 9.17
2067
+ show( m9.1 )
2068
+
2069
+ ## R code 9.18
2070
+ precis( m9.1 , 2 )
2071
+
2072
+ ## R code 9.19
2073
+ pairs( m9.1 )
2074
+
2075
+ ## R code 9.20
2076
+ traceplot( m9.1 )
2077
+
2078
+ ## R code 9.21
2079
+ trankplot( m9.1 )
2080
+
2081
+ ## R code 9.22
2082
+ y <- c(-1,1)
2083
+ set.seed(11)
2084
+ m9.2 <- ulam(
2085
+ alist(
2086
+ y ~ dnorm( mu , sigma ) ,
2087
+ mu <- alpha ,
2088
+ alpha ~ dnorm( 0 , 1000 ) ,
2089
+ sigma ~ dexp( 0.0001 )
2090
+ ) , data=list(y=y) , chains=3 )
2091
+
2092
+ ## R code 9.23
2093
+ precis( m9.2 )
2094
+
2095
+ ## R code 9.24
2096
+ set.seed(11)
2097
+ m9.3 <- ulam(
2098
+ alist(
2099
+ y ~ dnorm( mu , sigma ) ,
2100
+ mu <- alpha ,
2101
+ alpha ~ dnorm( 1 , 10 ) ,
2102
+ sigma ~ dexp( 1 )
2103
+ ) , data=list(y=y) , chains=3 )
2104
+ precis( m9.3 )
2105
+
2106
+ ## R code 9.25
2107
+ set.seed(41)
2108
+ y <- rnorm( 100 , mean=0 , sd=1 )
2109
+
2110
+ ## R code 9.26
2111
+ set.seed(384)
2112
+ m9.4 <- ulam(
2113
+ alist(
2114
+ y ~ dnorm( mu , sigma ) ,
2115
+ mu <- a1 + a2 ,
2116
+ a1 ~ dnorm( 0 , 1000 ),
2117
+ a2 ~ dnorm( 0 , 1000 ),
2118
+ sigma ~ dexp( 1 )
2119
+ ) , data=list(y=y) , chains=3 )
2120
+ precis( m9.4 )
2121
+
2122
+ ## R code 9.27
2123
+ m9.5 <- ulam(
2124
+ alist(
2125
+ y ~ dnorm( mu , sigma ) ,
2126
+ mu <- a1 + a2 ,
2127
+ a1 ~ dnorm( 0 , 10 ),
2128
+ a2 ~ dnorm( 0 , 10 ),
2129
+ sigma ~ dexp( 1 )
2130
+ ) , data=list(y=y) , chains=3 )
2131
+ precis( m9.5 )
2132
+
2133
+ ## R code 9.28
2134
+ mp <- ulam(
2135
+ alist(
2136
+ a ~ dnorm(0,1),
2137
+ b ~ dcauchy(0,1)
2138
+ ), data=list(y=1) , chains=1 )
2139
+
2140
+ ## R code 9.29
2141
+ m5.8s <- ulam(
2142
+ alist(
2143
+ height ~ dnorm( mu , sigma ) ,
2144
+ mu <- a + bl*leg_left + br*leg_right ,
2145
+ a ~ dnorm( 10 , 100 ) ,
2146
+ bl ~ dnorm( 2 , 10 ) ,
2147
+ br ~ dnorm( 2 , 10 ) ,
2148
+ sigma ~ dexp( 1 )
2149
+ ) , data=d, chains=4,
2150
+ start=list(a=10,bl=0,br=0.1,sigma=1) )
2151
+
2152
+ ## R code 9.30
2153
+ m5.8s2 <- ulam(
2154
+ alist(
2155
+ height ~ dnorm( mu , sigma ) ,
2156
+ mu <- a + bl*leg_left + br*leg_right ,
2157
+ a ~ dnorm( 10 , 100 ) ,
2158
+ bl ~ dnorm( 2 , 10 ) ,
2159
+ br ~ dnorm( 2 , 10 ) ,
2160
+ sigma ~ dexp( 1 )
2161
+ ) , data=d, chains=4,
2162
+ constraints=list(br="lower=0"),
2163
+ start=list(a=10,bl=0,br=0.1,sigma=1) )
2164
+
2165
+ ## R code 10.1
2166
+ p <- list()
2167
+ p$A <- c(0,0,10,0,0)
2168
+ p$B <- c(0,1,8,1,0)
2169
+ p$C <- c(0,2,6,2,0)
2170
+ p$D <- c(1,2,4,2,1)
2171
+ p$E <- c(2,2,2,2,2)
2172
+
2173
+ ## R code 10.2
2174
+ p_norm <- lapply( p , function(q) q/sum(q))
2175
+
2176
+ ## R code 10.3
2177
+ ( H <- sapply( p_norm , function(q) -sum(ifelse(q==0,0,q*log(q))) ) )
2178
+
2179
+ ## R code 10.4
2180
+ ways <- c(1,90,1260,37800,113400)
2181
+ logwayspp <- log(ways)/10
2182
+
2183
+ ## R code 10.5
2184
+ # build list of the candidate distributions
2185
+ p <- list()
2186
+ p[[1]] <- c(1/4,1/4,1/4,1/4)
2187
+ p[[2]] <- c(2/6,1/6,1/6,2/6)
2188
+ p[[3]] <- c(1/6,2/6,2/6,1/6)
2189
+ p[[4]] <- c(1/8,4/8,2/8,1/8)
2190
+
2191
+ # compute expected value of each
2192
+ sapply( p , function(p) sum(p*c(0,1,1,2)) )
2193
+
2194
+ ## R code 10.6
2195
+ # compute entropy of each distribution
2196
+ sapply( p , function(p) -sum( p*log(p) ) )
2197
+
2198
+ ## R code 10.7
2199
+ p <- 0.7
2200
+ ( A <- c( (1-p)^2 , p*(1-p) , (1-p)*p , p^2 ) )
2201
+
2202
+ ## R code 10.8
2203
+ -sum( A*log(A) )
2204
+
2205
+ ## R code 10.9
2206
+ sim.p <- function(G=1.4) {
2207
+ x123 <- runif(3)
2208
+ x4 <- ( (G)*sum(x123)-x123[2]-x123[3] )/(2-G)
2209
+ z <- sum( c(x123,x4) )
2210
+ p <- c( x123 , x4 )/z
2211
+ list( H=-sum( p*log(p) ) , p=p )
2212
+ }
2213
+
2214
+ ## R code 10.10
2215
+ H <- replicate( 1e5 , sim.p(1.4) )
2216
+ dens( as.numeric(H[1,]) , adj=0.1 )
2217
+
2218
+ ## R code 10.11
2219
+ entropies <- as.numeric(H[1,])
2220
+ distributions <- H[2,]
2221
+
2222
+ ## R code 10.12
2223
+ max(entropies)
2224
+
2225
+ ## R code 10.13
2226
+ distributions[ which.max(entropies) ]
2227
+
2228
+ ## R code 11.1
2229
+ library(rethinking)
2230
+ data(chimpanzees)
2231
+ d <- chimpanzees
2232
+
2233
+ ## R code 11.2
2234
+ d$treatment <- 1 + d$prosoc_left + 2*d$condition
2235
+
2236
+ ## R code 11.3
2237
+ xtabs( ~ treatment + prosoc_left + condition , d )
2238
+
2239
+ ## R code 11.4
2240
+ m11.1 <- quap(
2241
+ alist(
2242
+ pulled_left ~ dbinom( 1 , p ) ,
2243
+ logit(p) <- a ,
2244
+ a ~ dnorm( 0 , 10 )
2245
+ ) , data=d )
2246
+
2247
+ ## R code 11.5
2248
+ set.seed(1999)
2249
+ prior <- extract.prior( m11.1 , n=1e4 )
2250
+
2251
+ ## R code 11.6
2252
+ p <- inv_logit( prior$a )
2253
+ dens( p , adj=0.1 )
2254
+
2255
+ ## R code 11.7
2256
+ m11.2 <- quap(
2257
+ alist(
2258
+ pulled_left ~ dbinom( 1 , p ) ,
2259
+ logit(p) <- a + b[treatment] ,
2260
+ a ~ dnorm( 0 , 1.5 ),
2261
+ b[treatment] ~ dnorm( 0 , 10 )
2262
+ ) , data=d )
2263
+ set.seed(1999)
2264
+ prior <- extract.prior( m11.2 , n=1e4 )
2265
+ p <- sapply( 1:4 , function(k) inv_logit( prior$a + prior$b[,k] ) )
2266
+
2267
+ ## R code 11.8
2268
+ dens( abs( p[,1] - p[,2] ) , adj=0.1 )
2269
+
2270
+ ## R code 11.9
2271
+ m11.3 <- quap(
2272
+ alist(
2273
+ pulled_left ~ dbinom( 1 , p ) ,
2274
+ logit(p) <- a + b[treatment] ,
2275
+ a ~ dnorm( 0 , 1.5 ),
2276
+ b[treatment] ~ dnorm( 0 , 0.5 )
2277
+ ) , data=d )
2278
+ set.seed(1999)
2279
+ prior <- extract.prior( m11.3 , n=1e4 )
2280
+ p <- sapply( 1:4 , function(k) inv_logit( prior$a + prior$b[,k] ) )
2281
+ mean( abs( p[,1] - p[,2] ) )
2282
+
2283
+ ## R code 11.10
2284
+ # trimmed data list
2285
+ dat_list <- list(
2286
+ pulled_left = d$pulled_left,
2287
+ actor = d$actor,
2288
+ treatment = as.integer(d$treatment) )
2289
+
2290
+ ## R code 11.11
2291
+ m11.4 <- ulam(
2292
+ alist(
2293
+ pulled_left ~ dbinom( 1 , p ) ,
2294
+ logit(p) <- a[actor] + b[treatment] ,
2295
+ a[actor] ~ dnorm( 0 , 1.5 ),
2296
+ b[treatment] ~ dnorm( 0 , 0.5 )
2297
+ ) , data=dat_list , chains=4 , log_lik=TRUE )
2298
+ precis( m11.4 , depth=2 )
2299
+
2300
+ ## R code 11.12
2301
+ post <- extract.samples(m11.4)
2302
+ p_left <- inv_logit( post$a )
2303
+ plot( precis( as.data.frame(p_left) ) , xlim=c(0,1) )
2304
+
2305
+ ## R code 11.13
2306
+ labs <- c("R/N","L/N","R/P","L/P")
2307
+ plot( precis( m11.4 , depth=2 , pars="b" ) , labels=labs )
2308
+
2309
+ ## R code 11.14
2310
+ diffs <- list(
2311
+ db13 = post$b[,1] - post$b[,3],
2312
+ db24 = post$b[,2] - post$b[,4] )
2313
+ plot( precis(diffs) )
2314
+
2315
+ ## R code 11.15
2316
+ pl <- by( d$pulled_left , list( d$actor , d$treatment ) , mean )
2317
+ pl[1,]
2318
+
2319
+ ## R code 11.16
2320
+ plot( NULL , xlim=c(1,28) , ylim=c(0,1) , xlab="" ,
2321
+ ylab="proportion left lever" , xaxt="n" , yaxt="n" )
2322
+ axis( 2 , at=c(0,0.5,1) , labels=c(0,0.5,1) )
2323
+ abline( h=0.5 , lty=2 )
2324
+ for ( j in 1:7 ) abline( v=(j-1)*4+4.5 , lwd=0.5 )
2325
+ for ( j in 1:7 ) text( (j-1)*4+2.5 , 1.1 , concat("actor ",j) , xpd=TRUE )
2326
+ for ( j in (1:7)[-2] ) {
2327
+ lines( (j-1)*4+c(1,3) , pl[j,c(1,3)] , lwd=2 , col=rangi2 )
2328
+ lines( (j-1)*4+c(2,4) , pl[j,c(2,4)] , lwd=2 , col=rangi2 )
2329
+ }
2330
+ points( 1:28 , t(pl) , pch=16 , col="white" , cex=1.7 )
2331
+ points( 1:28 , t(pl) , pch=c(1,1,16,16) , col=rangi2 , lwd=2 )
2332
+ yoff <- 0.01
2333
+ text( 1 , pl[1,1]-yoff , "R/N" , pos=1 , cex=0.8 )
2334
+ text( 2 , pl[1,2]+yoff , "L/N" , pos=3 , cex=0.8 )
2335
+ text( 3 , pl[1,3]-yoff , "R/P" , pos=1 , cex=0.8 )
2336
+ text( 4 , pl[1,4]+yoff , "L/P" , pos=3 , cex=0.8 )
2337
+ mtext( "observed proportions\n" )
2338
+
2339
+ ## R code 11.17
2340
+ dat <- list( actor=rep(1:7,each=4) , treatment=rep(1:4,times=7) )
2341
+ p_post <- link( m11.4 , data=dat )
2342
+ p_mu <- apply( p_post , 2 , mean )
2343
+ p_ci <- apply( p_post , 2 , PI )
2344
+
2345
+ ## R code 11.18
2346
+ d$side <- d$prosoc_left + 1 # right 1, left 2
2347
+ d$cond <- d$condition + 1 # no partner 1, partner 2
2348
+
2349
+ ## R code 11.19
2350
+ dat_list2 <- list(
2351
+ pulled_left = d$pulled_left,
2352
+ actor = d$actor,
2353
+ side = d$side,
2354
+ cond = d$cond )
2355
+ m11.5 <- ulam(
2356
+ alist(
2357
+ pulled_left ~ dbinom( 1 , p ) ,
2358
+ logit(p) <- a[actor] + bs[side] + bc[cond] ,
2359
+ a[actor] ~ dnorm( 0 , 1.5 ),
2360
+ bs[side] ~ dnorm( 0 , 0.5 ),
2361
+ bc[cond] ~ dnorm( 0 , 0.5 )
2362
+ ) , data=dat_list2 , chains=4 , log_lik=TRUE )
2363
+
2364
+ ## R code 11.20
2365
+ compare( m11.5 , m11.4 , func=PSIS )
2366
+
2367
+ ## R code 11.21
2368
+ post <- extract.samples( m11.4 , clean=FALSE )
2369
+ str(post)
2370
+
2371
+ ## R code 11.22
2372
+ m11.4_stan_code <- stancode(m11.4)
2373
+ m11.4_stan <- stan( model_code=m11.4_stan_code , data=dat_list , chains=4 )
2374
+ compare( m11.4_stan , m11.4 )
2375
+
2376
+ ## R code 11.23
2377
+ post <- extract.samples(m11.4)
2378
+ mean( exp(post$b[,4]-post$b[,2]) )
2379
+
2380
+ ## R code 11.24
2381
+ data(chimpanzees)
2382
+ d <- chimpanzees
2383
+ d$treatment <- 1 + d$prosoc_left + 2*d$condition
2384
+ d$side <- d$prosoc_left + 1 # right 1, left 2
2385
+ d$cond <- d$condition + 1 # no partner 1, partner 2
2386
+ d_aggregated <- aggregate(
2387
+ d$pulled_left ,
2388
+ list( treatment=d$treatment , actor=d$actor ,
2389
+ side=d$side , cond=d$cond ) ,
2390
+ sum )
2391
+ colnames(d_aggregated)[5] <- "left_pulls"
2392
+
2393
+ ## R code 11.25
2394
+ dat <- with( d_aggregated , list(
2395
+ left_pulls = left_pulls,
2396
+ treatment = treatment,
2397
+ actor = actor,
2398
+ side = side,
2399
+ cond = cond ) )
2400
+
2401
+ m11.6 <- ulam(
2402
+ alist(
2403
+ left_pulls ~ dbinom( 18 , p ) ,
2404
+ logit(p) <- a[actor] + b[treatment] ,
2405
+ a[actor] ~ dnorm( 0 , 1.5 ) ,
2406
+ b[treatment] ~ dnorm( 0 , 0.5 )
2407
+ ) , data=dat , chains=4 , log_lik=TRUE )
2408
+
2409
+ ## R code 11.26
2410
+ compare( m11.6 , m11.4 , func=PSIS )
2411
+
2412
+ ## R code 11.27
2413
+ # deviance of aggregated 6-in-9
2414
+ -2*dbinom(6,9,0.2,log=TRUE)
2415
+ # deviance of dis-aggregated
2416
+ -2*sum(dbern(c(1,1,1,1,1,1,0,0,0),0.2,log=TRUE))
2417
+
2418
+ ## R code 11.28
2419
+ library(rethinking)
2420
+ data(UCBadmit)
2421
+ d <- UCBadmit
2422
+
2423
+ ## R code 11.29
2424
+ dat_list <- list(
2425
+ admit = d$admit,
2426
+ applications = d$applications,
2427
+ gid = ifelse( d$applicant.gender=="male" , 1 , 2 )
2428
+ )
2429
+ m11.7 <- ulam(
2430
+ alist(
2431
+ admit ~ dbinom( applications , p ) ,
2432
+ logit(p) <- a[gid] ,
2433
+ a[gid] ~ dnorm( 0 , 1.5 )
2434
+ ) , data=dat_list , chains=4 )
2435
+ precis( m11.7 , depth=2 )
2436
+
2437
+ ## R code 11.30
2438
+ post <- extract.samples(m11.7)
2439
+ diff_a <- post$a[,1] - post$a[,2]
2440
+ diff_p <- inv_logit(post$a[,1]) - inv_logit(post$a[,2])
2441
+ precis( list( diff_a=diff_a , diff_p=diff_p ) )
2442
+
2443
+ ## R code 11.31
2444
+ postcheck( m11.7 )
2445
+ # draw lines connecting points from same dept
2446
+ for ( i in 1:6 ) {
2447
+ x <- 1 + 2*(i-1)
2448
+ y1 <- d$admit[x]/d$applications[x]
2449
+ y2 <- d$admit[x+1]/d$applications[x+1]
2450
+ lines( c(x,x+1) , c(y1,y2) , col=rangi2 , lwd=2 )
2451
+ text( x+0.5 , (y1+y2)/2 + 0.05 , d$dept[x] , cex=0.8 , col=rangi2 )
2452
+ }
2453
+
2454
+ ## R code 11.32
2455
+ dat_list$dept_id <- rep(1:6,each=2)
2456
+ m11.8 <- ulam(
2457
+ alist(
2458
+ admit ~ dbinom( applications , p ) ,
2459
+ logit(p) <- a[gid] + delta[dept_id] ,
2460
+ a[gid] ~ dnorm( 0 , 1.5 ) ,
2461
+ delta[dept_id] ~ dnorm( 0 , 1.5 )
2462
+ ) , data=dat_list , chains=4 , iter=4000 )
2463
+ precis( m11.8 , depth=2 )
2464
+
2465
+ ## R code 11.33
2466
+ post <- extract.samples(m11.8)
2467
+ diff_a <- post$a[,1] - post$a[,2]
2468
+ diff_p <- inv_logit(post$a[,1]) - inv_logit(post$a[,2])
2469
+ precis( list( diff_a=diff_a , diff_p=diff_p ) )
2470
+
2471
+ ## R code 11.34
2472
+ pg <- with( dat_list , sapply( 1:6 , function(k)
2473
+ applications[dept_id==k]/sum(applications[dept_id==k]) ) )
2474
+ rownames(pg) <- c("male","female")
2475
+ colnames(pg) <- unique(d$dept)
2476
+ round( pg , 2 )
2477
+
2478
+ ## R code 11.35
2479
+ y <- rbinom(1e5,1000,1/1000)
2480
+ c( mean(y) , var(y) )
2481
+
2482
+ ## R code 11.36
2483
+ library(rethinking)
2484
+ data(Kline)
2485
+ d <- Kline
2486
+ d
2487
+
2488
+ ## R code 11.37
2489
+ d$P <- scale( log(d$population) )
2490
+ d$contact_id <- ifelse( d$contact=="high" , 2 , 1 )
2491
+
2492
+ ## R code 11.38
2493
+ curve( dlnorm( x , 0 , 10 ) , from=0 , to=100 , n=200 )
2494
+
2495
+ ## R code 11.39
2496
+ a <- rnorm(1e4,0,10)
2497
+ lambda <- exp(a)
2498
+ mean( lambda )
2499
+
2500
+ ## R code 11.40
2501
+ curve( dlnorm( x , 3 , 0.5 ) , from=0 , to=100 , n=200 )
2502
+
2503
+ ## R code 11.41
2504
+ N <- 100
2505
+ a <- rnorm( N , 3 , 0.5 )
2506
+ b <- rnorm( N , 0 , 10 )
2507
+ plot( NULL , xlim=c(-2,2) , ylim=c(0,100) )
2508
+ for ( i in 1:N ) curve( exp( a[i] + b[i]*x ) , add=TRUE , col=grau() )
2509
+
2510
+ ## R code 11.42
2511
+ set.seed(10)
2512
+ N <- 100
2513
+ a <- rnorm( N , 3 , 0.5 )
2514
+ b <- rnorm( N , 0 , 0.2 )
2515
+ plot( NULL , xlim=c(-2,2) , ylim=c(0,100) )
2516
+ for ( i in 1:N ) curve( exp( a[i] + b[i]*x ) , add=TRUE , col=grau() )
2517
+
2518
+ ## R code 11.43
2519
+ x_seq <- seq( from=log(100) , to=log(200000) , length.out=100 )
2520
+ lambda <- sapply( x_seq , function(x) exp( a + b*x ) )
2521
+ plot( NULL , xlim=range(x_seq) , ylim=c(0,500) , xlab="log population" ,
2522
+ ylab="total tools" )
2523
+ for ( i in 1:N ) lines( x_seq , lambda[i,] , col=grau() , lwd=1.5 )
2524
+
2525
+ ## R code 11.44
2526
+ plot( NULL , xlim=range(exp(x_seq)) , ylim=c(0,500) , xlab="population" ,
2527
+ ylab="total tools" )
2528
+ for ( i in 1:N ) lines( exp(x_seq) , lambda[i,] , col=grau() , lwd=1.5 )
2529
+
2530
+ ## R code 11.45
2531
+ dat <- list(
2532
+ T = d$total_tools ,
2533
+ P = d$P ,
2534
+ cid = d$contact_id )
2535
+
2536
+ # intercept only
2537
+ m11.9 <- ulam(
2538
+ alist(
2539
+ T ~ dpois( lambda ),
2540
+ log(lambda) <- a,
2541
+ a ~ dnorm( 3 , 0.5 )
2542
+ ), data=dat , chains=4 , log_lik=TRUE )
2543
+
2544
+ # interaction model
2545
+ m11.10 <- ulam(
2546
+ alist(
2547
+ T ~ dpois( lambda ),
2548
+ log(lambda) <- a[cid] + b[cid]*P,
2549
+ a[cid] ~ dnorm( 3 , 0.5 ),
2550
+ b[cid] ~ dnorm( 0 , 0.2 )
2551
+ ), data=dat , chains=4 , log_lik=TRUE )
2552
+
2553
+ ## R code 11.46
2554
+ compare( m11.9 , m11.10 , func=PSIS )
2555
+
2556
+ ## R code 11.47
2557
+ k <- PSIS( m11.10 , pointwise=TRUE )$k
2558
+ plot( dat$P , dat$T , xlab="log population (std)" , ylab="total tools" ,
2559
+ col=rangi2 , pch=ifelse( dat$cid==1 , 1 , 16 ) , lwd=2 ,
2560
+ ylim=c(0,75) , cex=1+normalize(k) )
2561
+
2562
+ # set up the horizontal axis values to compute predictions at
2563
+ ns <- 100
2564
+ P_seq <- seq( from=-1.4 , to=3 , length.out=ns )
2565
+
2566
+ # predictions for cid=1 (low contact)
2567
+ lambda <- link( m11.10 , data=data.frame( P=P_seq , cid=1 ) )
2568
+ lmu <- apply( lambda , 2 , mean )
2569
+ lci <- apply( lambda , 2 , PI )
2570
+ lines( P_seq , lmu , lty=2 , lwd=1.5 )
2571
+ shade( lci , P_seq , xpd=TRUE )
2572
+
2573
+ # predictions for cid=2 (high contact)
2574
+ lambda <- link( m11.10 , data=data.frame( P=P_seq , cid=2 ) )
2575
+ lmu <- apply( lambda , 2 , mean )
2576
+ lci <- apply( lambda , 2 , PI )
2577
+ lines( P_seq , lmu , lty=1 , lwd=1.5 )
2578
+ shade( lci , P_seq , xpd=TRUE )
2579
+
2580
+ ## R code 11.48
2581
+ plot( d$population , d$total_tools , xlab="population" , ylab="total tools" ,
2582
+ col=rangi2 , pch=ifelse( dat$cid==1 , 1 , 16 ) , lwd=2 ,
2583
+ ylim=c(0,75) , cex=1+normalize(k) )
2584
+
2585
+ ns <- 100
2586
+ P_seq <- seq( from=-5 , to=3 , length.out=ns )
2587
+ # 1.53 is sd of log(population)
2588
+ # 9 is mean of log(population)
2589
+ pop_seq <- exp( P_seq*1.53 + 9 )
2590
+
2591
+ lambda <- link( m11.10 , data=data.frame( P=P_seq , cid=1 ) )
2592
+ lmu <- apply( lambda , 2 , mean )
2593
+ lci <- apply( lambda , 2 , PI )
2594
+ lines( pop_seq , lmu , lty=2 , lwd=1.5 )
2595
+ shade( lci , pop_seq , xpd=TRUE )
2596
+
2597
+ lambda <- link( m11.10 , data=data.frame( P=P_seq , cid=2 ) )
2598
+ lmu <- apply( lambda , 2 , mean )
2599
+ lci <- apply( lambda , 2 , PI )
2600
+ lines( pop_seq , lmu , lty=1 , lwd=1.5 )
2601
+ shade( lci , pop_seq , xpd=TRUE )
2602
+
2603
+ ## R code 11.49
2604
+ dat2 <- list( T=d$total_tools, P=d$population, cid=d$contact_id )
2605
+ m11.11 <- ulam(
2606
+ alist(
2607
+ T ~ dpois( lambda ),
2608
+ lambda <- exp(a[cid])*P^b[cid]/g,
2609
+ a[cid] ~ dnorm(1,1),
2610
+ b[cid] ~ dexp(1),
2611
+ g ~ dexp(1)
2612
+ ), data=dat2 , chains=4 , log_lik=TRUE )
2613
+
2614
+ ## R code 11.50
2615
+ num_days <- 30
2616
+ y <- rpois( num_days , 1.5 )
2617
+
2618
+ ## R code 11.51
2619
+ num_weeks <- 4
2620
+ y_new <- rpois( num_weeks , 0.5*7 )
2621
+
2622
+ ## R code 11.52
2623
+ y_all <- c( y , y_new )
2624
+ exposure <- c( rep(1,30) , rep(7,4) )
2625
+ monastery <- c( rep(0,30) , rep(1,4) )
2626
+ d <- data.frame( y=y_all , days=exposure , monastery=monastery )
2627
+
2628
+ ## R code 11.53
2629
+ # compute the offset
2630
+ d$log_days <- log( d$days )
2631
+
2632
+ # fit the model
2633
+ m11.12 <- quap(
2634
+ alist(
2635
+ y ~ dpois( lambda ),
2636
+ log(lambda) <- log_days + a + b*monastery,
2637
+ a ~ dnorm( 0 , 1 ),
2638
+ b ~ dnorm( 0 , 1 )
2639
+ ), data=d )
2640
+
2641
+ ## R code 11.54
2642
+ post <- extract.samples( m11.12 )
2643
+ lambda_old <- exp( post$a )
2644
+ lambda_new <- exp( post$a + post$b )
2645
+ precis( data.frame( lambda_old , lambda_new ) )
2646
+
2647
+ ## R code 11.55
2648
+ # simulate career choices among 500 individuals
2649
+ N <- 500 # number of individuals
2650
+ income <- c(1,2,5) # expected income of each career
2651
+ score <- 0.5*income # scores for each career, based on income
2652
+ # next line converts scores to probabilities
2653
+ p <- softmax(score[1],score[2],score[3])
2654
+
2655
+ # now simulate choice
2656
+ # outcome career holds event type values, not counts
2657
+ career <- rep(NA,N) # empty vector of choices for each individual
2658
+ # sample chosen career for each individual
2659
+ set.seed(34302)
2660
+ for ( i in 1:N ) career[i] <- sample( 1:3 , size=1 , prob=p )
2661
+
2662
+ ## R code 11.56
2663
+ code_m11.13 <- "
2664
+ data{
2665
+ int N; // number of individuals
2666
+ int K; // number of possible careers
2667
+ int career[N]; // outcome
2668
+ vector[K] career_income;
2669
+ }
2670
+ parameters{
2671
+ vector[K-1] a; // intercepts
2672
+ real<lower=0> b; // association of income with choice
2673
+ }
2674
+ model{
2675
+ vector[K] p;
2676
+ vector[K] s;
2677
+ a ~ normal( 0 , 1 );
2678
+ b ~ normal( 0 , 0.5 );
2679
+ s[1] = a[1] + b*career_income[1];
2680
+ s[2] = a[2] + b*career_income[2];
2681
+ s[3] = 0; // pivot
2682
+ p = softmax( s );
2683
+ career ~ categorical( p );
2684
+ }
2685
+ "
2686
+
2687
+ ## R code 11.57
2688
+ dat_list <- list( N=N , K=3 , career=career , career_income=income )
2689
+ m11.13 <- stan( model_code=code_m11.13 , data=dat_list , chains=4 )
2690
+ precis( m11.13 , 2 )
2691
+
2692
+ ## R code 11.58
2693
+ post <- extract.samples( m11.13 )
2694
+
2695
+ # set up logit scores
2696
+ s1 <- with( post , a[,1] + b*income[1] )
2697
+ s2_orig <- with( post , a[,2] + b*income[2] )
2698
+ s2_new <- with( post , a[,2] + b*income[2]*2 )
2699
+
2700
+ # compute probabilities for original and counterfactual
2701
+ p_orig <- sapply( 1:length(post$b) , function(i)
2702
+ softmax( c(s1[i],s2_orig[i],0) ) )
2703
+ p_new <- sapply( 1:length(post$b) , function(i)
2704
+ softmax( c(s1[i],s2_new[i],0) ) )
2705
+
2706
+ # summarize
2707
+ p_diff <- p_new[2,] - p_orig[2,]
2708
+ precis( p_diff )
2709
+
2710
+ ## R code 11.59
2711
+ N <- 500
2712
+ # simulate family incomes for each individual
2713
+ family_income <- runif(N)
2714
+ # assign a unique coefficient for each type of event
2715
+ b <- c(-2,0,2)
2716
+ career <- rep(NA,N) # empty vector of choices for each individual
2717
+ for ( i in 1:N ) {
2718
+ score <- 0.5*(1:3) + b*family_income[i]
2719
+ p <- softmax(score[1],score[2],score[3])
2720
+ career[i] <- sample( 1:3 , size=1 , prob=p )
2721
+ }
2722
+
2723
+ code_m11.14 <- "
2724
+ data{
2725
+ int N; // number of observations
2726
+ int K; // number of outcome values
2727
+ int career[N]; // outcome
2728
+ real family_income[N];
2729
+ }
2730
+ parameters{
2731
+ vector[K-1] a; // intercepts
2732
+ vector[K-1] b; // coefficients on family income
2733
+ }
2734
+ model{
2735
+ vector[K] p;
2736
+ vector[K] s;
2737
+ a ~ normal(0,1.5);
2738
+ b ~ normal(0,1);
2739
+ for ( i in 1:N ) {
2740
+ for ( j in 1:(K-1) ) s[j] = a[j] + b[j]*family_income[i];
2741
+ s[K] = 0; // the pivot
2742
+ p = softmax( s );
2743
+ career[i] ~ categorical( p );
2744
+ }
2745
+ }
2746
+ "
2747
+
2748
+ dat_list <- list( N=N , K=3 , career=career , family_income=family_income )
2749
+ m11.14 <- stan( model_code=code_m11.14 , data=dat_list , chains=4 )
2750
+ precis( m11.14 , 2 )
2751
+
2752
+ ## R code 11.60
2753
+ library(rethinking)
2754
+ data(UCBadmit)
2755
+ d <- UCBadmit
2756
+
2757
+ ## R code 11.61
2758
+ # binomial model of overall admission probability
2759
+ m_binom <- quap(
2760
+ alist(
2761
+ admit ~ dbinom(applications,p),
2762
+ logit(p) <- a,
2763
+ a ~ dnorm( 0 , 1.5 )
2764
+ ), data=d )
2765
+
2766
+ # Poisson model of overall admission rate and rejection rate
2767
+ # 'reject' is a reserved word in Stan, cannot use as variable name
2768
+ dat <- list( admit=d$admit , rej=d$reject )
2769
+ m_pois <- ulam(
2770
+ alist(
2771
+ admit ~ dpois(lambda1),
2772
+ rej ~ dpois(lambda2),
2773
+ log(lambda1) <- a1,
2774
+ log(lambda2) <- a2,
2775
+ c(a1,a2) ~ dnorm(0,1.5)
2776
+ ), data=dat , chains=3 , cores=3 )
2777
+
2778
+ ## R code 11.62
2779
+ inv_logit(coef(m_binom))
2780
+
2781
+ ## R code 11.63
2782
+ k <- coef(m_pois)
2783
+ a1 <- k['a1']; a2 <- k['a2']
2784
+ exp(a1)/(exp(a1)+exp(a2))
2785
+
2786
+ ## R code 12.1
2787
+ pbar <- 0.5
2788
+ theta <- 5
2789
+ curve( dbeta2(x,pbar,theta) , from=0 , to=1 ,
2790
+ xlab="probability" , ylab="Density" )
2791
+
2792
+ ## R code 12.2
2793
+ library(rethinking)
2794
+ data(UCBadmit)
2795
+ d <- UCBadmit
2796
+ d$gid <- ifelse( d$applicant.gender=="male" , 1L , 2L )
2797
+ dat <- list( A=d$admit , N=d$applications , gid=d$gid )
2798
+ m12.1 <- ulam(
2799
+ alist(
2800
+ A ~ dbetabinom( N , pbar , theta ),
2801
+ logit(pbar) <- a[gid],
2802
+ a[gid] ~ dnorm( 0 , 1.5 ),
2803
+ transpars> theta <<- phi + 2.0,
2804
+ phi ~ dexp(1)
2805
+ ), data=dat , chains=4 )
2806
+
2807
+ ## R code 12.3
2808
+ post <- extract.samples( m12.1 )
2809
+ post$da <- post$a[,1] - post$a[,2]
2810
+ precis( post , depth=2 )
2811
+
2812
+ ## R code 12.4
2813
+ gid <- 2
2814
+ # draw posterior mean beta distribution
2815
+ curve( dbeta2(x,mean(logistic(post$a[,gid])),mean(post$theta)) , from=0 , to=1 ,
2816
+ ylab="Density" , xlab="probability admit", ylim=c(0,3) , lwd=2 )
2817
+
2818
+ # draw 50 beta distributions sampled from posterior
2819
+ for ( i in 1:50 ) {
2820
+ p <- logistic( post$a[i,gid] )
2821
+ theta <- post$theta[i]
2822
+ curve( dbeta2(x,p,theta) , add=TRUE , col=col.alpha("black",0.2) )
2823
+ }
2824
+ mtext( "distribution of female admission rates" )
2825
+
2826
+ ## R code 12.5
2827
+ postcheck( m12.1 )
2828
+
2829
+ ## R code 12.6
2830
+ library(rethinking)
2831
+ data(Kline)
2832
+ d <- Kline
2833
+ d$P <- standardize( log(d$population) )
2834
+ d$contact_id <- ifelse( d$contact=="high" , 2L , 1L )
2835
+
2836
+ dat2 <- list(
2837
+ T = d$total_tools,
2838
+ P = d$population,
2839
+ cid = d$contact_id )
2840
+
2841
+ m12.2 <- ulam(
2842
+ alist(
2843
+ T ~ dgampois( lambda , phi ),
2844
+ lambda <- exp(a[cid])*P^b[cid] / g,
2845
+ a[cid] ~ dnorm(1,1),
2846
+ b[cid] ~ dexp(1),
2847
+ g ~ dexp(1),
2848
+ phi ~ dexp(1)
2849
+ ), data=dat2 , chains=4 , log_lik=TRUE )
2850
+
2851
+ ## R code 12.7
2852
+ # define parameters
2853
+ prob_drink <- 0.2 # 20% of days
2854
+ rate_work <- 1 # average 1 manuscript per day
2855
+
2856
+ # sample one year of production
2857
+ N <- 365
2858
+
2859
+ # simulate days monks drink
2860
+ set.seed(365)
2861
+ drink <- rbinom( N , 1 , prob_drink )
2862
+
2863
+ # simulate manuscripts completed
2864
+ y <- (1-drink)*rpois( N , rate_work )
2865
+
2866
+ ## R code 12.8
2867
+ simplehist( y , xlab="manuscripts completed" , lwd=4 )
2868
+ zeros_drink <- sum(drink)
2869
+ zeros_work <- sum(y==0 & drink==0)
2870
+ zeros_total <- sum(y==0)
2871
+ lines( c(0,0) , c(zeros_work,zeros_total) , lwd=4 , col=rangi2 )
2872
+
2873
+ ## R code 12.9
2874
+ m12.3 <- ulam(
2875
+ alist(
2876
+ y ~ dzipois( p , lambda ),
2877
+ logit(p) <- ap,
2878
+ log(lambda) <- al,
2879
+ ap ~ dnorm( -1.5 , 1 ),
2880
+ al ~ dnorm( 1 , 0.5 )
2881
+ ) , data=list(y=y) , chains=4 )
2882
+ precis( m12.3 )
2883
+
2884
+ ## R code 12.10
2885
+ post <- extract.samples( m12.3 )
2886
+ mean( inv_logit( post$ap ) ) # probability drink
2887
+ mean( exp( post$al ) ) # rate finish manuscripts, when not drinking
2888
+
2889
+ ## R code 12.11
2890
+ m12.3_alt <- ulam(
2891
+ alist(
2892
+ y|y>0 ~ custom( log1m(p) + poisson_lpmf(y|lambda) ),
2893
+ y|y==0 ~ custom( log_mix( p , 0 , poisson_lpmf(0|lambda) ) ),
2894
+ logit(p) <- ap,
2895
+ log(lambda) <- al,
2896
+ ap ~ dnorm(-1.5,1),
2897
+ al ~ dnorm(1,0.5)
2898
+ ) , data=list(y=as.integer(y)) , chains=4 )
2899
+
2900
+ ## R code 12.12
2901
+ library(rethinking)
2902
+ data(Trolley)
2903
+ d <- Trolley
2904
+
2905
+ ## R code 12.13
2906
+ simplehist( d$response , xlim=c(1,7) , xlab="response" )
2907
+
2908
+ ## R code 12.14
2909
+ # discrete proportion of each response value
2910
+ pr_k <- table( d$response ) / nrow(d)
2911
+
2912
+ # cumsum converts to cumulative proportions
2913
+ cum_pr_k <- cumsum( pr_k )
2914
+
2915
+ # plot
2916
+ plot( 1:7 , cum_pr_k , type="b" , xlab="response" ,
2917
+ ylab="cumulative proportion" , ylim=c(0,1) )
2918
+
2919
+ ## R code 12.15
2920
+ logit <- function(x) log(x/(1-x)) # convenience function
2921
+ round( lco <- logit( cum_pr_k ) , 2 )
2922
+
2923
+ ## R code 12.16
2924
+ m12.4 <- ulam(
2925
+ alist(
2926
+ R ~ dordlogit( 0 , cutpoints ),
2927
+ cutpoints ~ dnorm( 0 , 1.5 )
2928
+ ) , data=list( R=d$response ), chains=4 , cores=4 )
2929
+
2930
+ ## R code 12.17
2931
+ m12.4q <- quap(
2932
+ alist(
2933
+ response ~ dordlogit( 0 , c(a1,a2,a3,a4,a5,a6) ),
2934
+ c(a1,a2,a3,a4,a5,a6) ~ dnorm( 0 , 1.5 )
2935
+ ) , data=d , start=list(a1=-2,a2=-1,a3=0,a4=1,a5=2,a6=2.5) )
2936
+
2937
+ ## R code 12.18
2938
+ precis( m12.4 , depth=2 )
2939
+
2940
+ ## R code 12.19
2941
+ round( inv_logit(coef(m12.4)) , 3 )
2942
+
2943
+ ## R code 12.20
2944
+ round( pk <- dordlogit( 1:7 , 0 , coef(m12.4) ) , 2 )
2945
+
2946
+ ## R code 12.21
2947
+ sum( pk*(1:7) )
2948
+
2949
+ ## R code 12.22
2950
+ round( pk <- dordlogit( 1:7 , 0 , coef(m12.4)-0.5 ) , 2 )
2951
+
2952
+ ## R code 12.23
2953
+ sum( pk*(1:7) )
2954
+
2955
+ ## R code 12.24
2956
+ dat <- list(
2957
+ R = d$response,
2958
+ A = d$action,
2959
+ I = d$intention,
2960
+ C = d$contact )
2961
+ m12.5 <- ulam(
2962
+ alist(
2963
+ R ~ dordlogit( phi , cutpoints ),
2964
+ phi <- bA*A + bC*C + BI*I ,
2965
+ BI <- bI + bIA*A + bIC*C ,
2966
+ c(bA,bI,bC,bIA,bIC) ~ dnorm( 0 , 0.5 ),
2967
+ cutpoints ~ dnorm( 0 , 1.5 )
2968
+ ) , data=dat , chains=4 , cores=4 )
2969
+ precis( m12.5 )
2970
+
2971
+ ## R code 12.25
2972
+ plot( precis(m12.5) , xlim=c(-1.4,0) )
2973
+
2974
+ ## R code 12.26
2975
+ plot( NULL , type="n" , xlab="intention" , ylab="probability" ,
2976
+ xlim=c(0,1) , ylim=c(0,1) , xaxp=c(0,1,1) , yaxp=c(0,1,2) )
2977
+
2978
+ ## R code 12.27
2979
+ kA <- 0 # value for action
2980
+ kC <- 0 # value for contact
2981
+ kI <- 0:1 # values of intention to calculate over
2982
+ pdat <- data.frame(A=kA,C=kC,I=kI)
2983
+ phi <- link( m12.5 , data=pdat )$phi
2984
+
2985
+ ## R code 12.28
2986
+ post <- extract.samples( m12.5 )
2987
+ for ( s in 1:50 ) {
2988
+ pk <- pordlogit( 1:6 , phi[s,] , post$cutpoints[s,] )
2989
+ for ( i in 1:6 ) lines( kI , pk[,i] , col=grau(0.1) )
2990
+ }
2991
+
2992
+ ## R code 12.29
2993
+ kA <- 0 # value for action
2994
+ kC <- 1 # value for contact
2995
+ kI <- 0:1 # values of intention to calculate over
2996
+ pdat <- data.frame(A=kA,C=kC,I=kI)
2997
+ s <- sim( m12.5 , data=pdat )
2998
+ simplehist( s , xlab="response" )
2999
+
3000
+ ## R code 12.30
3001
+ library(rethinking)
3002
+ data(Trolley)
3003
+ d <- Trolley
3004
+ levels(d$edu)
3005
+
3006
+ ## R code 12.31
3007
+ edu_levels <- c( 6 , 1 , 8 , 4 , 7 , 2 , 5 , 3 )
3008
+ d$edu_new <- edu_levels[ d$edu ]
3009
+
3010
+ ## R code 12.32
3011
+ library(gtools)
3012
+ set.seed(1805)
3013
+ delta <- rdirichlet( 10 , alpha=rep(2,7) )
3014
+ str(delta)
3015
+
3016
+ ## R code 12.33
3017
+ h <- 3
3018
+ plot( NULL , xlim=c(1,7) , ylim=c(0,0.4) , xlab="index" , ylab="probability" )
3019
+ for ( i in 1:nrow(delta) ) lines( 1:7 , delta[i,] , type="b" ,
3020
+ pch=ifelse(i==h,16,1) , lwd=ifelse(i==h,4,1.5) ,
3021
+ col=ifelse(i==h,"black",col.alpha("black",0.7)) )
3022
+
3023
+ ## R code 12.34
3024
+ dat <- list(
3025
+ R = d$response ,
3026
+ action = d$action,
3027
+ intention = d$intention,
3028
+ contact = d$contact,
3029
+ E = as.integer( d$edu_new ), # edu_new as an index
3030
+ alpha = rep( 2 , 7 ) ) # delta prior
3031
+
3032
+ m12.6 <- ulam(
3033
+ alist(
3034
+ R ~ ordered_logistic( phi , kappa ),
3035
+ phi <- bE*sum( delta_j[1:E] ) + bA*action + bI*intention + bC*contact,
3036
+ kappa ~ normal( 0 , 1.5 ),
3037
+ c(bA,bI,bC,bE) ~ normal( 0 , 1 ),
3038
+ vector[8]: delta_j <<- append_row( 0 , delta ),
3039
+ simplex[7]: delta ~ dirichlet( alpha )
3040
+ ), data=dat , chains=4 , cores=4 )
3041
+
3042
+ ## R code 12.35
3043
+ precis( m12.6 , depth=2 , omit="kappa" )
3044
+
3045
+ ## R code 12.36
3046
+ delta_labels <- c("Elem","MidSch","SHS","HSG","SCol","Bach","Mast","Grad")
3047
+ pairs( m12.6 , pars="delta" , labels=delta_labels )
3048
+
3049
+ ## R code 12.37
3050
+ dat$edu_norm <- normalize( d$edu_new )
3051
+ m12.7 <- ulam(
3052
+ alist(
3053
+ R ~ ordered_logistic( mu , cutpoints ),
3054
+ mu <- bE*edu_norm + bA*action + bI*intention + bC*contact,
3055
+ c(bA,bI,bC,bE) ~ normal( 0 , 1 ),
3056
+ cutpoints ~ normal( 0 , 1.5 )
3057
+ ), data=dat , chains=4 , cores=4 )
3058
+ precis( m12.7 )
3059
+
3060
+ ## R code 12.38
3061
+ library(rethinking)
3062
+ data(Hurricanes)
3063
+
3064
+ ## R code 13.1
3065
+ library(rethinking)
3066
+ data(reedfrogs)
3067
+ d <- reedfrogs
3068
+ str(d)
3069
+
3070
+ ## R code 13.2
3071
+ # make the tank cluster variable
3072
+ d$tank <- 1:nrow(d)
3073
+
3074
+ dat <- list(
3075
+ S = d$surv,
3076
+ N = d$density,
3077
+ tank = d$tank )
3078
+
3079
+ # approximate posterior
3080
+ m13.1 <- ulam(
3081
+ alist(
3082
+ S ~ dbinom( N , p ) ,
3083
+ logit(p) <- a[tank] ,
3084
+ a[tank] ~ dnorm( 0 , 1.5 )
3085
+ ), data=dat , chains=4 , log_lik=TRUE )
3086
+
3087
+ ## R code 13.3
3088
+ m13.2 <- ulam(
3089
+ alist(
3090
+ S ~ dbinom( N , p ) ,
3091
+ logit(p) <- a[tank] ,
3092
+ a[tank] ~ dnorm( a_bar , sigma ) ,
3093
+ a_bar ~ dnorm( 0 , 1.5 ) ,
3094
+ sigma ~ dexp( 1 )
3095
+ ), data=dat , chains=4 , log_lik=TRUE )
3096
+
3097
+ ## R code 13.4
3098
+ compare( m13.1 , m13.2 )
3099
+
3100
+ ## R code 13.5
3101
+ # extract Stan samples
3102
+ post <- extract.samples(m13.2)
3103
+
3104
+ # compute mean intercept for each tank
3105
+ # also transform to probability with logistic
3106
+ d$propsurv.est <- logistic( apply( post$a , 2 , mean ) )
3107
+
3108
+ # display raw proportions surviving in each tank
3109
+ plot( d$propsurv , ylim=c(0,1) , pch=16 , xaxt="n" ,
3110
+ xlab="tank" , ylab="proportion survival" , col=rangi2 )
3111
+ axis( 1 , at=c(1,16,32,48) , labels=c(1,16,32,48) )
3112
+
3113
+ # overlay posterior means
3114
+ points( d$propsurv.est )
3115
+
3116
+ # mark posterior mean probability across tanks
3117
+ abline( h=mean(inv_logit(post$a_bar)) , lty=2 )
3118
+
3119
+ # draw vertical dividers between tank densities
3120
+ abline( v=16.5 , lwd=0.5 )
3121
+ abline( v=32.5 , lwd=0.5 )
3122
+ text( 8 , 0 , "small tanks" )
3123
+ text( 16+8 , 0 , "medium tanks" )
3124
+ text( 32+8 , 0 , "large tanks" )
3125
+
3126
+ ## R code 13.6
3127
+ # show first 100 populations in the posterior
3128
+ plot( NULL , xlim=c(-3,4) , ylim=c(0,0.35) ,
3129
+ xlab="log-odds survive" , ylab="Density" )
3130
+ for ( i in 1:100 )
3131
+ curve( dnorm(x,post$a_bar[i],post$sigma[i]) , add=TRUE ,
3132
+ col=col.alpha("black",0.2) )
3133
+
3134
+ # sample 8000 imaginary tanks from the posterior distribution
3135
+ sim_tanks <- rnorm( 8000 , post$a_bar , post$sigma )
3136
+
3137
+ # transform to probability and visualize
3138
+ dens( inv_logit(sim_tanks) , lwd=2 , adj=0.1 )
3139
+
3140
+ ## R code 13.7
3141
+ a_bar <- 1.5
3142
+ sigma <- 1.5
3143
+ nponds <- 60
3144
+ Ni <- as.integer( rep( c(5,10,25,35) , each=15 ) )
3145
+
3146
+ ## R code 13.8
3147
+ set.seed(5005)
3148
+ a_pond <- rnorm( nponds , mean=a_bar , sd=sigma )
3149
+
3150
+ ## R code 13.9
3151
+ dsim <- data.frame( pond=1:nponds , Ni=Ni , true_a=a_pond )
3152
+
3153
+ ## R code 13.10
3154
+ class(1:3)
3155
+ class(c(1,2,3))
3156
+
3157
+ ## R code 13.11
3158
+ dsim$Si <- rbinom( nponds , prob=logistic(dsim$true_a) , size=dsim$Ni )
3159
+
3160
+ ## R code 13.12
3161
+ dsim$p_nopool <- dsim$Si / dsim$Ni
3162
+
3163
+ ## R code 13.13
3164
+ dat <- list( Si=dsim$Si , Ni=dsim$Ni , pond=dsim$pond )
3165
+ m13.3 <- ulam(
3166
+ alist(
3167
+ Si ~ dbinom( Ni , p ),
3168
+ logit(p) <- a_pond[pond],
3169
+ a_pond[pond] ~ dnorm( a_bar , sigma ),
3170
+ a_bar ~ dnorm( 0 , 1.5 ),
3171
+ sigma ~ dexp( 1 )
3172
+ ), data=dat , chains=4 )
3173
+
3174
+ ## R code 13.14
3175
+ precis( m13.3 , depth=2 )
3176
+
3177
+ ## R code 13.15
3178
+ post <- extract.samples( m13.3 )
3179
+ dsim$p_partpool <- apply( inv_logit(post$a_pond) , 2 , mean )
3180
+
3181
+ ## R code 13.16
3182
+ dsim$p_true <- inv_logit( dsim$true_a )
3183
+
3184
+ ## R code 13.17
3185
+ nopool_error <- abs( dsim$p_nopool - dsim$p_true )
3186
+ partpool_error <- abs( dsim$p_partpool - dsim$p_true )
3187
+
3188
+ ## R code 13.18
3189
+ plot( 1:60 , nopool_error , xlab="pond" , ylab="absolute error" ,
3190
+ col=rangi2 , pch=16 )
3191
+ points( 1:60 , partpool_error )
3192
+
3193
+ ## R code 13.19
3194
+ nopool_avg <- aggregate(nopool_error,list(dsim$Ni),mean)
3195
+ partpool_avg <- aggregate(partpool_error,list(dsim$Ni),mean)
3196
+
3197
+ ## R code 13.20
3198
+ a <- 1.5
3199
+ sigma <- 1.5
3200
+ nponds <- 60
3201
+ Ni <- as.integer( rep( c(5,10,25,35) , each=15 ) )
3202
+ a_pond <- rnorm( nponds , mean=a , sd=sigma )
3203
+ dsim <- data.frame( pond=1:nponds , Ni=Ni , true_a=a_pond )
3204
+ dsim$Si <- rbinom( nponds,prob=inv_logit( dsim$true_a ),size=dsim$Ni )
3205
+ dsim$p_nopool <- dsim$Si / dsim$Ni
3206
+ newdat <- list(Si=dsim$Si,Ni=dsim$Ni,pond=1:nponds)
3207
+ m13.3new <- stan( fit=m13.3@stanfit , data=newdat , chains=4 )
3208
+
3209
+ post <- extract.samples( m13.3new )
3210
+ dsim$p_partpool <- apply( inv_logit(post$a_pond) , 2 , mean )
3211
+ dsim$p_true <- inv_logit( dsim$true_a )
3212
+ nopool_error <- abs( dsim$p_nopool - dsim$p_true )
3213
+ partpool_error <- abs( dsim$p_partpool - dsim$p_true )
3214
+ plot( 1:60 , nopool_error , xlab="pond" , ylab="absolute error" , col=rangi2 , pch=16 )
3215
+ points( 1:60 , partpool_error )
3216
+
3217
+ ## R code 13.21
3218
+ library(rethinking)
3219
+ data(chimpanzees)
3220
+ d <- chimpanzees
3221
+ d$treatment <- 1 + d$prosoc_left + 2*d$condition
3222
+
3223
+ dat_list <- list(
3224
+ pulled_left = d$pulled_left,
3225
+ actor = d$actor,
3226
+ block_id = d$block,
3227
+ treatment = as.integer(d$treatment) )
3228
+
3229
+ set.seed(13)
3230
+ m13.4 <- ulam(
3231
+ alist(
3232
+ pulled_left ~ dbinom( 1 , p ) ,
3233
+ logit(p) <- a[actor] + g[block_id] + b[treatment] ,
3234
+ b[treatment] ~ dnorm( 0 , 0.5 ),
3235
+ ## adaptive priors
3236
+ a[actor] ~ dnorm( a_bar , sigma_a ),
3237
+ g[block_id] ~ dnorm( 0 , sigma_g ),
3238
+ ## hyper-priors
3239
+ a_bar ~ dnorm( 0 , 1.5 ),
3240
+ sigma_a ~ dexp(1),
3241
+ sigma_g ~ dexp(1)
3242
+ ) , data=dat_list , chains=4 , cores=4 , log_lik=TRUE )
3243
+
3244
+ ## R code 13.22
3245
+ precis( m13.4 , depth=2 )
3246
+ plot( precis(m13.4,depth=2) ) # also plot
3247
+
3248
+ ## R code 13.23
3249
+ set.seed(14)
3250
+ m13.5 <- ulam(
3251
+ alist(
3252
+ pulled_left ~ dbinom( 1 , p ) ,
3253
+ logit(p) <- a[actor] + b[treatment] ,
3254
+ b[treatment] ~ dnorm( 0 , 0.5 ),
3255
+ a[actor] ~ dnorm( a_bar , sigma_a ),
3256
+ a_bar ~ dnorm( 0 , 1.5 ),
3257
+ sigma_a ~ dexp(1)
3258
+ ) , data=dat_list , chains=4 , cores=4 , log_lik=TRUE )
3259
+
3260
+ ## R code 13.24
3261
+ compare( m13.4 , m13.5 )
3262
+
3263
+ ## R code 13.25
3264
+ set.seed(15)
3265
+ m13.6 <- ulam(
3266
+ alist(
3267
+ pulled_left ~ dbinom( 1 , p ) ,
3268
+ logit(p) <- a[actor] + g[block_id] + b[treatment] ,
3269
+ b[treatment] ~ dnorm( 0 , sigma_b ),
3270
+ a[actor] ~ dnorm( a_bar , sigma_a ),
3271
+ g[block_id] ~ dnorm( 0 , sigma_g ),
3272
+ a_bar ~ dnorm( 0 , 1.5 ),
3273
+ sigma_a ~ dexp(1),
3274
+ sigma_g ~ dexp(1),
3275
+ sigma_b ~ dexp(1)
3276
+ ) , data=dat_list , chains=4 , cores=4 , log_lik=TRUE )
3277
+ coeftab( m13.4 , m13.6 )
3278
+
3279
+ ## R code 13.26
3280
+ m13.7 <- ulam(
3281
+ alist(
3282
+ v ~ normal(0,3),
3283
+ x ~ normal(0,exp(v))
3284
+ ), data=list(N=1) , chains=4 )
3285
+ precis( m13.7 )
3286
+
3287
+ ## R code 13.27
3288
+ m13.7nc <- ulam(
3289
+ alist(
3290
+ v ~ normal(0,3),
3291
+ z ~ normal(0,1),
3292
+ gq> real[1]:x <<- z*exp(v)
3293
+ ), data=list(N=1) , chains=4 )
3294
+ precis( m13.7nc )
3295
+
3296
+ ## R code 13.28
3297
+ set.seed(13)
3298
+ m13.4b <- ulam( m13.4 , chains=4 , cores=4 , control=list(adapt_delta=0.99) )
3299
+ divergent(m13.4b)
3300
+
3301
+ ## R code 13.29
3302
+ set.seed(13)
3303
+ m13.4nc <- ulam(
3304
+ alist(
3305
+ pulled_left ~ dbinom( 1 , p ) ,
3306
+ logit(p) <- a_bar + z[actor]*sigma_a + # actor intercepts
3307
+ x[block_id]*sigma_g + # block intercepts
3308
+ b[treatment] ,
3309
+ b[treatment] ~ dnorm( 0 , 0.5 ),
3310
+ z[actor] ~ dnorm( 0 , 1 ),
3311
+ x[block_id] ~ dnorm( 0 , 1 ),
3312
+ a_bar ~ dnorm( 0 , 1.5 ),
3313
+ sigma_a ~ dexp(1),
3314
+ sigma_g ~ dexp(1),
3315
+ gq> vector[actor]:a <<- a_bar + z*sigma_a,
3316
+ gq> vector[block_id]:g <<- x*sigma_g
3317
+ ) , data=dat_list , chains=4 , cores=4 )
3318
+
3319
+ ## R code 13.30
3320
+ precis_c <- precis( m13.4 , depth=2 )
3321
+ precis_nc <- precis( m13.4nc , depth=2 )
3322
+ pars <- c( paste("a[",1:7,"]",sep="") , paste("g[",1:6,"]",sep="") ,
3323
+ paste("b[",1:4,"]",sep="") , "a_bar" , "sigma_a" , "sigma_g" )
3324
+ neff_table <- cbind( precis_c[pars,"n_eff"] , precis_nc[pars,"n_eff"] )
3325
+ plot( neff_table , xlim=range(neff_table) , ylim=range(neff_table) ,
3326
+ xlab="n_eff (centered)" , ylab="n_eff (non-centered)" , lwd=2 )
3327
+ abline( a=0 , b=1 , lty=2 )
3328
+
3329
+ ## R code 13.31
3330
+ chimp <- 2
3331
+ d_pred <- list(
3332
+ actor = rep(chimp,4),
3333
+ treatment = 1:4,
3334
+ block_id = rep(1,4)
3335
+ )
3336
+ p <- link( m13.4 , data=d_pred )
3337
+ p_mu <- apply( p , 2 , mean )
3338
+ p_ci <- apply( p , 2 , PI )
3339
+
3340
+ ## R code 13.32
3341
+ post <- extract.samples(m13.4)
3342
+ str(post)
3343
+
3344
+ ## R code 13.33
3345
+ dens( post$a[,5] )
3346
+
3347
+ ## R code 13.34
3348
+ p_link <- function( treatment , actor=1 , block_id=1 ) {
3349
+ logodds <- with( post ,
3350
+ a[,actor] + g[,block_id] + b[,treatment] )
3351
+ return( inv_logit(logodds) )
3352
+ }
3353
+
3354
+ ## R code 13.35
3355
+ p_raw <- sapply( 1:4 , function(i) p_link( i , actor=2 , block_id=1 ) )
3356
+ p_mu <- apply( p_raw , 2 , mean )
3357
+ p_ci <- apply( p_raw , 2 , PI )
3358
+
3359
+ ## R code 13.36
3360
+ p_link_abar <- function( treatment ) {
3361
+ logodds <- with( post , a_bar + b[,treatment] )
3362
+ return( inv_logit(logodds) )
3363
+ }
3364
+
3365
+ ## R code 13.37
3366
+ post <- extract.samples(m13.4)
3367
+ p_raw <- sapply( 1:4 , function(i) p_link_abar( i ) )
3368
+ p_mu <- apply( p_raw , 2 , mean )
3369
+ p_ci <- apply( p_raw , 2 , PI )
3370
+
3371
+ plot( NULL , xlab="treatment" , ylab="proportion pulled left" ,
3372
+ ylim=c(0,1) , xaxt="n" , xlim=c(1,4) )
3373
+ axis( 1 , at=1:4 , labels=c("R/N","L/N","R/P","L/P") )
3374
+ lines( 1:4 , p_mu )
3375
+ shade( p_ci , 1:4 )
3376
+
3377
+ ## R code 13.38
3378
+ a_sim <- with( post , rnorm( length(post$a_bar) , a_bar , sigma_a ) )
3379
+ p_link_asim <- function( treatment ) {
3380
+ logodds <- with( post , a_sim + b[,treatment] )
3381
+ return( inv_logit(logodds) )
3382
+ }
3383
+ p_raw_asim <- sapply( 1:4 , function(i) p_link_asim( i ) )
3384
+
3385
+ ## R code 13.39
3386
+ plot( NULL , xlab="treatment" , ylab="proportion pulled left" ,
3387
+ ylim=c(0,1) , xaxt="n" , xlim=c(1,4) )
3388
+ axis( 1 , at=1:4 , labels=c("R/N","L/N","R/P","L/P") )
3389
+ for ( i in 1:100 ) lines( 1:4 , p_raw_asim[i,] , col=grau(0.25) , lwd=2 )
3390
+
3391
+ ## R code 13.40
3392
+ ## R code 13.41
3393
+ ## R code 14.1
3394
+ a <- 3.5 # average morning wait time
3395
+ b <- (-1) # average difference afternoon wait time
3396
+ sigma_a <- 1 # std dev in intercepts
3397
+ sigma_b <- 0.5 # std dev in slopes
3398
+ rho <- (-0.7) # correlation between intercepts and slopes
3399
+
3400
+ ## R code 14.2
3401
+ Mu <- c( a , b )
3402
+
3403
+ ## R code 14.3
3404
+ cov_ab <- sigma_a*sigma_b*rho
3405
+ Sigma <- matrix( c(sigma_a^2,cov_ab,cov_ab,sigma_b^2) , ncol=2 )
3406
+
3407
+ ## R code 14.4
3408
+ matrix( c(1,2,3,4) , nrow=2 , ncol=2 )
3409
+
3410
+ ## R code 14.5
3411
+ sigmas <- c(sigma_a,sigma_b) # standard deviations
3412
+ Rho <- matrix( c(1,rho,rho,1) , nrow=2 ) # correlation matrix
3413
+
3414
+ # now matrix multiply to get covariance matrix
3415
+ Sigma <- diag(sigmas) %*% Rho %*% diag(sigmas)
3416
+
3417
+ ## R code 14.6
3418
+ N_cafes <- 20
3419
+
3420
+ ## R code 14.7
3421
+ library(MASS)
3422
+ set.seed(5) # used to replicate example
3423
+ vary_effects <- mvrnorm( N_cafes , Mu , Sigma )
3424
+
3425
+ ## R code 14.8
3426
+ a_cafe <- vary_effects[,1]
3427
+ b_cafe <- vary_effects[,2]
3428
+
3429
+ ## R code 14.9
3430
+ plot( a_cafe , b_cafe , col=rangi2 ,
3431
+ xlab="intercepts (a_cafe)" , ylab="slopes (b_cafe)" )
3432
+
3433
+ # overlay population distribution
3434
+ library(ellipse)
3435
+ for ( l in c(0.1,0.3,0.5,0.8,0.99) )
3436
+ lines(ellipse(Sigma,centre=Mu,level=l),col=col.alpha("black",0.2))
3437
+
3438
+ ## R code 14.10
3439
+ set.seed(22)
3440
+ N_visits <- 10
3441
+ afternoon <- rep(0:1,N_visits*N_cafes/2)
3442
+ cafe_id <- rep( 1:N_cafes , each=N_visits )
3443
+ mu <- a_cafe[cafe_id] + b_cafe[cafe_id]*afternoon
3444
+ sigma <- 0.5 # std dev within cafes
3445
+ wait <- rnorm( N_visits*N_cafes , mu , sigma )
3446
+ d <- data.frame( cafe=cafe_id , afternoon=afternoon , wait=wait )
3447
+
3448
+ ## R code 14.11
3449
+ R <- rlkjcorr( 1e4 , K=2 , eta=2 )
3450
+ dens( R[,1,2] , xlab="correlation" )
3451
+
3452
+ ## R code 14.12
3453
+ set.seed(867530)
3454
+ m14.1 <- ulam(
3455
+ alist(
3456
+ wait ~ normal( mu , sigma ),
3457
+ mu <- a_cafe[cafe] + b_cafe[cafe]*afternoon,
3458
+ c(a_cafe,b_cafe)[cafe] ~ multi_normal( c(a,b) , Rho , sigma_cafe ),
3459
+ a ~ normal(5,2),
3460
+ b ~ normal(-1,0.5),
3461
+ sigma_cafe ~ exponential(1),
3462
+ sigma ~ exponential(1),
3463
+ Rho ~ lkj_corr(2)
3464
+ ) , data=d , chains=4 , cores=4 )
3465
+
3466
+ ## R code 14.13
3467
+ post <- extract.samples(m14.1)
3468
+ dens( post$Rho[,1,2] , xlim=c(-1,1) ) # posterior
3469
+ R <- rlkjcorr( 1e4 , K=2 , eta=2 ) # prior
3470
+ dens( R[,1,2] , add=TRUE , lty=2 )
3471
+
3472
+ ## R code 14.14
3473
+ # compute unpooled estimates directly from data
3474
+ a1 <- sapply( 1:N_cafes ,
3475
+ function(i) mean(wait[cafe_id==i & afternoon==0]) )
3476
+ b1 <- sapply( 1:N_cafes ,
3477
+ function(i) mean(wait[cafe_id==i & afternoon==1]) ) - a1
3478
+
3479
+ # extract posterior means of partially pooled estimates
3480
+ post <- extract.samples(m14.1)
3481
+ a2 <- apply( post$a_cafe , 2 , mean )
3482
+ b2 <- apply( post$b_cafe , 2 , mean )
3483
+
3484
+ # plot both and connect with lines
3485
+ plot( a1 , b1 , xlab="intercept" , ylab="slope" ,
3486
+ pch=16 , col=rangi2 , ylim=c( min(b1)-0.1 , max(b1)+0.1 ) ,
3487
+ xlim=c( min(a1)-0.1 , max(a1)+0.1 ) )
3488
+ points( a2 , b2 , pch=1 )
3489
+ for ( i in 1:N_cafes ) lines( c(a1[i],a2[i]) , c(b1[i],b2[i]) )
3490
+
3491
+ ## R code 14.15
3492
+ # compute posterior mean bivariate Gaussian
3493
+ Mu_est <- c( mean(post$a) , mean(post$b) )
3494
+ rho_est <- mean( post$Rho[,1,2] )
3495
+ sa_est <- mean( post$sigma_cafe[,1] )
3496
+ sb_est <- mean( post$sigma_cafe[,2] )
3497
+ cov_ab <- sa_est*sb_est*rho_est
3498
+ Sigma_est <- matrix( c(sa_est^2,cov_ab,cov_ab,sb_est^2) , ncol=2 )
3499
+
3500
+ # draw contours
3501
+ library(ellipse)
3502
+ for ( l in c(0.1,0.3,0.5,0.8,0.99) )
3503
+ lines(ellipse(Sigma_est,centre=Mu_est,level=l),
3504
+ col=col.alpha("black",0.2))
3505
+
3506
+ ## R code 14.16
3507
+ # convert varying effects to waiting times
3508
+ wait_morning_1 <- (a1)
3509
+ wait_afternoon_1 <- (a1 + b1)
3510
+ wait_morning_2 <- (a2)
3511
+ wait_afternoon_2 <- (a2 + b2)
3512
+
3513
+ # plot both and connect with lines
3514
+ plot( wait_morning_1 , wait_afternoon_1 , xlab="morning wait" ,
3515
+ ylab="afternoon wait" , pch=16 , col=rangi2 ,
3516
+ ylim=c( min(wait_afternoon_1)-0.1 , max(wait_afternoon_1)+0.1 ) ,
3517
+ xlim=c( min(wait_morning_1)-0.1 , max(wait_morning_1)+0.1 ) )
3518
+ points( wait_morning_2 , wait_afternoon_2 , pch=1 )
3519
+ for ( i in 1:N_cafes )
3520
+ lines( c(wait_morning_1[i],wait_morning_2[i]) ,
3521
+ c(wait_afternoon_1[i],wait_afternoon_2[i]) )
3522
+ abline( a=0 , b=1 , lty=2 )
3523
+
3524
+ ## R code 14.17
3525
+ # now shrinkage distribution by simulation
3526
+ v <- mvrnorm( 1e4 , Mu_est , Sigma_est )
3527
+ v[,2] <- v[,1] + v[,2] # calculate afternoon wait
3528
+ Sigma_est2 <- cov(v)
3529
+ Mu_est2 <- Mu_est
3530
+ Mu_est2[2] <- Mu_est[1]+Mu_est[2]
3531
+
3532
+ # draw contours
3533
+ library(ellipse)
3534
+ for ( l in c(0.1,0.3,0.5,0.8,0.99) )
3535
+ lines(ellipse(Sigma_est2,centre=Mu_est2,level=l),
3536
+ col=col.alpha("black",0.5))
3537
+
3538
+ ## R code 14.18
3539
+ library(rethinking)
3540
+ data(chimpanzees)
3541
+ d <- chimpanzees
3542
+ d$block_id <- d$block
3543
+ d$treatment <- 1L + d$prosoc_left + 2L*d$condition
3544
+
3545
+ dat <- list(
3546
+ L = d$pulled_left,
3547
+ tid = d$treatment,
3548
+ actor = d$actor,
3549
+ block_id = as.integer(d$block_id) )
3550
+
3551
+ set.seed(4387510)
3552
+ m14.2 <- ulam(
3553
+ alist(
3554
+ L ~ dbinom(1,p),
3555
+ logit(p) <- g[tid] + alpha[actor,tid] + beta[block_id,tid],
3556
+
3557
+ # adaptive priors
3558
+ vector[4]:alpha[actor] ~ multi_normal(0,Rho_actor,sigma_actor),
3559
+ vector[4]:beta[block_id] ~ multi_normal(0,Rho_block,sigma_block),
3560
+
3561
+ # fixed priors
3562
+ g[tid] ~ dnorm(0,1),
3563
+ sigma_actor ~ dexp(1),
3564
+ Rho_actor ~ dlkjcorr(4),
3565
+ sigma_block ~ dexp(1),
3566
+ Rho_block ~ dlkjcorr(4)
3567
+ ) , data=dat , chains=4 , cores=4 )
3568
+
3569
+ ## R code 14.19
3570
+ set.seed(4387510)
3571
+ m14.3 <- ulam(
3572
+ alist(
3573
+ L ~ binomial(1,p),
3574
+ logit(p) <- g[tid] + alpha[actor,tid] + beta[block_id,tid],
3575
+
3576
+ # adaptive priors - non-centered
3577
+ transpars> matrix[actor,4]:alpha <-
3578
+ compose_noncentered( sigma_actor , L_Rho_actor , z_actor ),
3579
+ transpars> matrix[block_id,4]:beta <-
3580
+ compose_noncentered( sigma_block , L_Rho_block , z_block ),
3581
+ matrix[4,actor]:z_actor ~ normal( 0 , 1 ),
3582
+ matrix[4,block_id]:z_block ~ normal( 0 , 1 ),
3583
+
3584
+ # fixed priors
3585
+ g[tid] ~ normal(0,1),
3586
+ vector[4]:sigma_actor ~ dexp(1),
3587
+ cholesky_factor_corr[4]:L_Rho_actor ~ lkj_corr_cholesky( 2 ),
3588
+ vector[4]:sigma_block ~ dexp(1),
3589
+ cholesky_factor_corr[4]:L_Rho_block ~ lkj_corr_cholesky( 2 ),
3590
+
3591
+ # compute ordinary correlation matrixes from Cholesky factors
3592
+ gq> matrix[4,4]:Rho_actor <<- Chol_to_Corr(L_Rho_actor),
3593
+ gq> matrix[4,4]:Rho_block <<- Chol_to_Corr(L_Rho_block)
3594
+ ) , data=dat , chains=4 , cores=4 , log_lik=TRUE )
3595
+
3596
+ ## R code 14.20
3597
+ # extract n_eff values for each model
3598
+ neff_nc <- precis(m14.3,3,pars=c("alpha","beta"))$n_eff
3599
+ neff_c <- precis(m14.2,3,pars=c("alpha","beta"))$n_eff
3600
+ plot( neff_c , neff_nc , xlab="centered (default)" ,
3601
+ ylab="non-centered (cholesky)" , lwd=1.5 )
3602
+ abline(a=0,b=1,lty=2)
3603
+
3604
+ ## R code 14.21
3605
+ precis( m14.3 , depth=2 , pars=c("sigma_actor","sigma_block") )
3606
+
3607
+ ## R code 14.22
3608
+ # compute mean for each actor in each treatment
3609
+ pl <- by( d$pulled_left , list( d$actor , d$treatment ) , mean )
3610
+
3611
+ # generate posterior predictions using link
3612
+ datp <- list(
3613
+ actor=rep(1:7,each=4) ,
3614
+ tid=rep(1:4,times=7) ,
3615
+ block_id=rep(5,times=4*7) )
3616
+ p_post <- link( m14.3 , data=datp )
3617
+ p_mu <- apply( p_post , 2 , mean )
3618
+ p_ci <- apply( p_post , 2 , PI )
3619
+
3620
+ # set up plot
3621
+ plot( NULL , xlim=c(1,28) , ylim=c(0,1) , xlab="" ,
3622
+ ylab="proportion left lever" , xaxt="n" , yaxt="n" )
3623
+ axis( 2 , at=c(0,0.5,1) , labels=c(0,0.5,1) )
3624
+ abline( h=0.5 , lty=2 )
3625
+ for ( j in 1:7 ) abline( v=(j-1)*4+4.5 , lwd=0.5 )
3626
+ for ( j in 1:7 ) text( (j-1)*4+2.5 , 1.1 , concat("actor ",j) , xpd=TRUE )
3627
+
3628
+ xo <- 0.1 # offset distance to stagger raw data and predictions
3629
+ # raw data
3630
+ for ( j in (1:7)[-2] ) {
3631
+ lines( (j-1)*4+c(1,3)-xo , pl[j,c(1,3)] , lwd=2 , col=rangi2 )
3632
+ lines( (j-1)*4+c(2,4)-xo , pl[j,c(2,4)] , lwd=2 , col=rangi2 )
3633
+ }
3634
+ points( 1:28-xo , t(pl) , pch=16 , col="white" , cex=1.7 )
3635
+ points( 1:28-xo , t(pl) , pch=c(1,1,16,16) , col=rangi2 , lwd=2 )
3636
+
3637
+ yoff <- 0.175
3638
+ text( 1-xo , pl[1,1]-yoff , "R/N" , pos=1 , cex=0.8 )
3639
+ text( 2-xo , pl[1,2]+yoff , "L/N" , pos=3 , cex=0.8 )
3640
+ text( 3-xo , pl[1,3]-yoff , "R/P" , pos=1 , cex=0.8 )
3641
+ text( 4-xo , pl[1,4]+yoff , "L/P" , pos=3 , cex=0.8 )
3642
+
3643
+ # posterior predictions
3644
+ for ( j in (1:7)[-2] ) {
3645
+ lines( (j-1)*4+c(1,3)+xo , p_mu[(j-1)*4+c(1,3)] , lwd=2 )
3646
+ lines( (j-1)*4+c(2,4)+xo , p_mu[(j-1)*4+c(2,4)] , lwd=2 )
3647
+ }
3648
+ for ( i in 1:28 ) lines( c(i,i)+xo , p_ci[,i] , lwd=1 )
3649
+ points( 1:28+xo , p_mu , pch=16 , col="white" , cex=1.3 )
3650
+ points( 1:28+xo , p_mu , pch=c(1,1,16,16) )
3651
+
3652
+ ## R code 14.23
3653
+ set.seed(73)
3654
+ N <- 500
3655
+ U_sim <- rnorm( N )
3656
+ Q_sim <- sample( 1:4 , size=N , replace=TRUE )
3657
+ E_sim <- rnorm( N , U_sim + Q_sim )
3658
+ W_sim <- rnorm( N , U_sim + 0*E_sim )
3659
+ dat_sim <- list(
3660
+ W=standardize(W_sim) ,
3661
+ E=standardize(E_sim) ,
3662
+ Q=standardize(Q_sim) )
3663
+
3664
+ ## R code 14.24
3665
+ m14.4 <- ulam(
3666
+ alist(
3667
+ W ~ dnorm( mu , sigma ),
3668
+ mu <- aW + bEW*E,
3669
+ aW ~ dnorm( 0 , 0.2 ),
3670
+ bEW ~ dnorm( 0 , 0.5 ),
3671
+ sigma ~ dexp( 1 )
3672
+ ) , data=dat_sim , chains=4 , cores=4 )
3673
+ precis( m14.4 )
3674
+
3675
+ ## R code 14.25
3676
+ m14.5 <- ulam(
3677
+ alist(
3678
+ W ~ dnorm( mu , sigma ),
3679
+ mu <- aW + bEW*E + bQW*Q,
3680
+ aW ~ dnorm( 0 , 0.2 ),
3681
+ bEW ~ dnorm( 0 , 0.5 ),
3682
+ bQW ~ dnorm( 0 , 0.5 ),
3683
+ sigma ~ dexp( 1 )
3684
+ ) , data=dat_sim , chains=4 , cores=4 )
3685
+ precis( m14.5 )
3686
+
3687
+ ## R code 14.26
3688
+ m14.6 <- ulam(
3689
+ alist(
3690
+ c(W,E) ~ multi_normal( c(muW,muE) , Rho , Sigma ),
3691
+ muW <- aW + bEW*E,
3692
+ muE <- aE + bQE*Q,
3693
+ c(aW,aE) ~ normal( 0 , 0.2 ),
3694
+ c(bEW,bQE) ~ normal( 0 , 0.5 ),
3695
+ Rho ~ lkj_corr( 2 ),
3696
+ Sigma ~ exponential( 1 )
3697
+ ), data=dat_sim , chains=4 , cores=4 )
3698
+ precis( m14.6 , depth=3 )
3699
+
3700
+ ## R code 14.27
3701
+ m14.4x <- ulam( m14.4 , data=dat_sim , chains=4 , cores=4 )
3702
+ m14.6x <- ulam( m14.6 , data=dat_sim , chains=4 , cores=4 )
3703
+
3704
+ ## R code 14.28
3705
+ set.seed(73)
3706
+ N <- 500
3707
+ U_sim <- rnorm( N )
3708
+ Q_sim <- sample( 1:4 , size=N , replace=TRUE )
3709
+ E_sim <- rnorm( N , U_sim + Q_sim )
3710
+ W_sim <- rnorm( N , -U_sim + 0.2*E_sim )
3711
+ dat_sim <- list(
3712
+ W=standardize(W_sim) ,
3713
+ E=standardize(E_sim) ,
3714
+ Q=standardize(Q_sim) )
3715
+
3716
+ ## R code 14.29
3717
+ library(dagitty)
3718
+ dagIV <- dagitty( "dag{ Q -> E <- U -> W <- E }" )
3719
+ instrumentalVariables( dagIV , exposure="E" , outcome="W" )
3720
+
3721
+ ## R code 14.30
3722
+ library(rethinking)
3723
+ data(KosterLeckie)
3724
+
3725
+ ## R code 14.31
3726
+ kl_data <- list(
3727
+ N = nrow(kl_dyads),
3728
+ N_households = max(kl_dyads$hidB),
3729
+ did = kl_dyads$did,
3730
+ hidA = kl_dyads$hidA,
3731
+ hidB = kl_dyads$hidB,
3732
+ giftsAB = kl_dyads$giftsAB,
3733
+ giftsBA = kl_dyads$giftsBA
3734
+ )
3735
+
3736
+ m14.7 <- ulam(
3737
+ alist(
3738
+ giftsAB ~ poisson( lambdaAB ),
3739
+ giftsBA ~ poisson( lambdaBA ),
3740
+ log(lambdaAB) <- a + gr[hidA,1] + gr[hidB,2] + d[did,1] ,
3741
+ log(lambdaBA) <- a + gr[hidB,1] + gr[hidA,2] + d[did,2] ,
3742
+ a ~ normal(0,1),
3743
+
3744
+ ## gr matrix of varying effects
3745
+ vector[2]:gr[N_households] ~ multi_normal(0,Rho_gr,sigma_gr),
3746
+ Rho_gr ~ lkj_corr(4),
3747
+ sigma_gr ~ exponential(1),
3748
+
3749
+ ## dyad effects
3750
+ transpars> matrix[N,2]:d <-
3751
+ compose_noncentered( rep_vector(sigma_d,2) , L_Rho_d , z ),
3752
+ matrix[2,N]:z ~ normal( 0 , 1 ),
3753
+ cholesky_factor_corr[2]:L_Rho_d ~ lkj_corr_cholesky( 8 ),
3754
+ sigma_d ~ exponential(1),
3755
+
3756
+ ## compute correlation matrix for dyads
3757
+ gq> matrix[2,2]:Rho_d <<- Chol_to_Corr( L_Rho_d )
3758
+ ), data=kl_data , chains=4 , cores=4 , iter=2000 )
3759
+
3760
+ ## R code 14.32
3761
+ precis( m14.7 , depth=3 , pars=c("Rho_gr","sigma_gr") )
3762
+
3763
+ ## R code 14.33
3764
+ post <- extract.samples( m14.7 )
3765
+ g <- sapply( 1:25 , function(i) post$a + post$gr[,i,1] )
3766
+ r <- sapply( 1:25 , function(i) post$a + post$gr[,i,2] )
3767
+ Eg_mu <- apply( exp(g) , 2 , mean )
3768
+ Er_mu <- apply( exp(r) , 2 , mean )
3769
+
3770
+ ## R code 14.34
3771
+ plot( NULL , xlim=c(0,8.6) , ylim=c(0,8.6) , xlab="generalized giving" ,
3772
+ ylab="generalized receiving" , lwd=1.5 )
3773
+ abline(a=0,b=1,lty=2)
3774
+
3775
+ # ellipses
3776
+ library(ellipse)
3777
+ for ( i in 1:25 ) {
3778
+ Sigma <- cov( cbind( g[,i] , r[,i] ) )
3779
+ Mu <- c( mean(g[,i]) , mean(r[,i]) )
3780
+ for ( l in c(0.5) ) {
3781
+ el <- ellipse( Sigma , centre=Mu , level=l )
3782
+ lines( exp(el) , col=col.alpha("black",0.5) )
3783
+ }
3784
+ }
3785
+ # household means
3786
+ points( Eg_mu , Er_mu , pch=21 , bg="white" , lwd=1.5 )
3787
+
3788
+ ## R code 14.35
3789
+ precis( m14.7 , depth=3 , pars=c("Rho_d","sigma_d") )
3790
+
3791
+ ## R code 14.36
3792
+ dy1 <- apply( post$d[,,1] , 2 , mean )
3793
+ dy2 <- apply( post$d[,,2] , 2 , mean )
3794
+ plot( dy1 , dy2 )
3795
+
3796
+ ## R code 14.37
3797
+ # load the distance matrix
3798
+ library(rethinking)
3799
+ data(islandsDistMatrix)
3800
+
3801
+ # display (measured in thousands of km)
3802
+ Dmat <- islandsDistMatrix
3803
+ colnames(Dmat) <- c("Ml","Ti","SC","Ya","Fi","Tr","Ch","Mn","To","Ha")
3804
+ round(Dmat,1)
3805
+
3806
+ ## R code 14.38
3807
+ # linear
3808
+ curve( exp(-1*x) , from=0 , to=4 , lty=2 )
3809
+ # squared
3810
+ curve( exp(-1*x^2) , add=TRUE )
3811
+
3812
+ ## R code 14.39
3813
+ data(Kline2) # load the ordinary data, now with coordinates
3814
+ d <- Kline2
3815
+ d$society <- 1:10 # index observations
3816
+
3817
+ dat_list <- list(
3818
+ T = d$total_tools,
3819
+ P = d$population,
3820
+ society = d$society,
3821
+ Dmat=islandsDistMatrix )
3822
+
3823
+ m14.8 <- ulam(
3824
+ alist(
3825
+ T ~ dpois(lambda),
3826
+ lambda <- (a*P^b/g)*exp(k[society]),
3827
+ vector[10]:k ~ multi_normal( 0 , SIGMA ),
3828
+ matrix[10,10]:SIGMA <- cov_GPL2( Dmat , etasq , rhosq , 0.01 ),
3829
+ c(a,b,g) ~ dexp( 1 ),
3830
+ etasq ~ dexp( 2 ),
3831
+ rhosq ~ dexp( 0.5 )
3832
+ ), data=dat_list , chains=4 , cores=4 , iter=2000 )
3833
+
3834
+ ## R code 14.40
3835
+ precis( m14.8 , depth=3 )
3836
+
3837
+ ## R code 14.41
3838
+ post <- extract.samples(m14.8)
3839
+
3840
+ # plot the posterior median covariance function
3841
+ plot( NULL , xlab="distance (thousand km)" , ylab="covariance" ,
3842
+ xlim=c(0,10) , ylim=c(0,2) )
3843
+
3844
+ # compute posterior mean covariance
3845
+ x_seq <- seq( from=0 , to=10 , length.out=100 )
3846
+ pmcov <- sapply( x_seq , function(x) post$etasq*exp(-post$rhosq*x^2) )
3847
+ pmcov_mu <- apply( pmcov , 2 , mean )
3848
+ lines( x_seq , pmcov_mu , lwd=2 )
3849
+
3850
+ # plot 50 functions sampled from posterior
3851
+ for ( i in 1:50 )
3852
+ curve( post$etasq[i]*exp(-post$rhosq[i]*x^2) , add=TRUE ,
3853
+ col=col.alpha("black",0.3) )
3854
+
3855
+ ## R code 14.42
3856
+ # compute posterior median covariance among societies
3857
+ K <- matrix(0,nrow=10,ncol=10)
3858
+ for ( i in 1:10 )
3859
+ for ( j in 1:10 )
3860
+ K[i,j] <- median(post$etasq) *
3861
+ exp( -median(post$rhosq) * islandsDistMatrix[i,j]^2 )
3862
+ diag(K) <- median(post$etasq) + 0.01
3863
+
3864
+ ## R code 14.43
3865
+ # convert to correlation matrix
3866
+ Rho <- round( cov2cor(K) , 2 )
3867
+ # add row/col names for convenience
3868
+ colnames(Rho) <- c("Ml","Ti","SC","Ya","Fi","Tr","Ch","Mn","To","Ha")
3869
+ rownames(Rho) <- colnames(Rho)
3870
+ Rho
3871
+
3872
+ ## R code 14.44
3873
+ # scale point size to logpop
3874
+ psize <- d$logpop / max(d$logpop)
3875
+ psize <- exp(psize*1.5)-2
3876
+
3877
+ # plot raw data and labels
3878
+ plot( d$lon2 , d$lat , xlab="longitude" , ylab="latitude" ,
3879
+ col=rangi2 , cex=psize , pch=16 , xlim=c(-50,30) )
3880
+ labels <- as.character(d$culture)
3881
+ text( d$lon2 , d$lat , labels=labels , cex=0.7 , pos=c(2,4,3,3,4,1,3,2,4,2) )
3882
+
3883
+ # overlay lines shaded by Rho
3884
+ for( i in 1:10 )
3885
+ for ( j in 1:10 )
3886
+ if ( i < j )
3887
+ lines( c( d$lon2[i],d$lon2[j] ) , c( d$lat[i],d$lat[j] ) ,
3888
+ lwd=2 , col=col.alpha("black",Rho[i,j]^2) )
3889
+
3890
+ ## R code 14.45
3891
+ # compute posterior median relationship, ignoring distance
3892
+ logpop.seq <- seq( from=6 , to=14 , length.out=30 )
3893
+ lambda <- sapply( logpop.seq , function(lp) exp( post$a + post$bp*lp ) )
3894
+ lambda.median <- apply( lambda , 2 , median )
3895
+ lambda.PI80 <- apply( lambda , 2 , PI , prob=0.8 )
3896
+
3897
+ # plot raw data and labels
3898
+ plot( d$logpop , d$total_tools , col=rangi2 , cex=psize , pch=16 ,
3899
+ xlab="log population" , ylab="total tools" )
3900
+ text( d$logpop , d$total_tools , labels=labels , cex=0.7 ,
3901
+ pos=c(4,3,4,2,2,1,4,4,4,2) )
3902
+
3903
+ # display posterior predictions
3904
+ lines( logpop.seq , lambda.median , lty=2 )
3905
+ lines( logpop.seq , lambda.PI80[1,] , lty=2 )
3906
+ lines( logpop.seq , lambda.PI80[2,] , lty=2 )
3907
+
3908
+ # overlay correlations
3909
+ for( i in 1:10 )
3910
+ for ( j in 1:10 )
3911
+ if ( i < j )
3912
+ lines( c( d$logpop[i],d$logpop[j] ) ,
3913
+ c( d$total_tools[i],d$total_tools[j] ) ,
3914
+ lwd=2 , col=col.alpha("black",Rho[i,j]^2) )
3915
+
3916
+ ## R code 14.46
3917
+ m14.8nc <- ulam(
3918
+ alist(
3919
+ T ~ dpois(lambda),
3920
+ lambda <- (a*P^b/g)*exp(k[society]),
3921
+
3922
+ # non-centered Gaussian Process prior
3923
+ transpars> vector[10]: k <<- L_SIGMA * z,
3924
+ vector[10]: z ~ normal( 0 , 1 ),
3925
+ transpars> matrix[10,10]: L_SIGMA <<- cholesky_decompose( SIGMA ),
3926
+ transpars> matrix[10,10]: SIGMA <- cov_GPL2( Dmat , etasq , rhosq , 0.01 ),
3927
+
3928
+ c(a,b,g) ~ dexp( 1 ),
3929
+ etasq ~ dexp( 2 ),
3930
+ rhosq ~ dexp( 0.5 )
3931
+ ), data=dat_list , chains=4 , cores=4 , iter=2000 )
3932
+
3933
+ ## R code 14.47
3934
+ library(rethinking)
3935
+ data(Primates301)
3936
+ data(Primates301_nex)
3937
+
3938
+ # plot it using ape package - install.packages('ape') if needed
3939
+ library(ape)
3940
+ plot( ladderize(Primates301_nex) , type="fan" , font=1 , no.margin=TRUE ,
3941
+ label.offset=1 , cex=0.5 )
3942
+
3943
+ ## R code 14.48
3944
+ d <- Primates301
3945
+ d$name <- as.character(d$name)
3946
+ dstan <- d[ complete.cases( d$group_size , d$body , d$brain ) , ]
3947
+ spp_obs <- dstan$name
3948
+
3949
+ ## R code 14.49
3950
+ dat_list <- list(
3951
+ N_spp = nrow(dstan),
3952
+ M = standardize(log(dstan$body)),
3953
+ B = standardize(log(dstan$brain)),
3954
+ G = standardize(log(dstan$group_size)),
3955
+ Imat = diag(nrow(dstan)) )
3956
+
3957
+ m14.9 <- ulam(
3958
+ alist(
3959
+ B ~ multi_normal( mu , SIGMA ),
3960
+ mu <- a + bM*M + bG*G,
3961
+ matrix[N_spp,N_spp]: SIGMA <- Imat * sigma_sq,
3962
+ a ~ normal( 0 , 1 ),
3963
+ c(bM,bG) ~ normal( 0 , 0.5 ),
3964
+ sigma_sq ~ exponential( 1 )
3965
+ ), data=dat_list , chains=4 , cores=4 )
3966
+ precis( m14.9 )
3967
+
3968
+ ## R code 14.50
3969
+ library(ape)
3970
+ tree_trimmed <- keep.tip( Primates301_nex, spp_obs )
3971
+ Rbm <- corBrownian( phy=tree_trimmed )
3972
+ V <- vcv(Rbm)
3973
+ Dmat <- cophenetic( tree_trimmed )
3974
+ plot( Dmat , V , xlab="phylogenetic distance" , ylab="covariance" )
3975
+
3976
+ ## R code 14.51
3977
+ # put species in right order
3978
+ dat_list$V <- V[ spp_obs , spp_obs ]
3979
+ # convert to correlation matrix
3980
+ dat_list$R <- dat_list$V / max(V)
3981
+
3982
+ # Brownian motion model
3983
+ m14.10 <- ulam(
3984
+ alist(
3985
+ B ~ multi_normal( mu , SIGMA ),
3986
+ mu <- a + bM*M + bG*G,
3987
+ matrix[N_spp,N_spp]: SIGMA <- R * sigma_sq,
3988
+ a ~ normal( 0 , 1 ),
3989
+ c(bM,bG) ~ normal( 0 , 0.5 ),
3990
+ sigma_sq ~ exponential( 1 )
3991
+ ), data=dat_list , chains=4 , cores=4 )
3992
+ precis( m14.10 )
3993
+
3994
+ ## R code 14.52
3995
+ # add scaled and reordered distance matrix
3996
+ dat_list$Dmat <- Dmat[ spp_obs , spp_obs ] / max(Dmat)
3997
+
3998
+ m14.11 <- ulam(
3999
+ alist(
4000
+ B ~ multi_normal( mu , SIGMA ),
4001
+ mu <- a + bM*M + bG*G,
4002
+ matrix[N_spp,N_spp]: SIGMA <- cov_GPL1( Dmat , etasq , rhosq , 0.01 ),
4003
+ a ~ normal(0,1),
4004
+ c(bM,bG) ~ normal(0,0.5),
4005
+ etasq ~ half_normal(1,0.25),
4006
+ rhosq ~ half_normal(3,0.25)
4007
+ ), data=dat_list , chains=4 , cores=4 )
4008
+ precis( m14.11 )
4009
+
4010
+ ## R code 14.53
4011
+ post <- extract.samples(m14.11)
4012
+ plot( NULL , xlim=c(0,max(dat_list$Dmat)) , ylim=c(0,1.5) ,
4013
+ xlab="phylogenetic distance" , ylab="covariance" )
4014
+
4015
+ # posterior
4016
+ for ( i in 1:30 )
4017
+ curve( post$etasq[i]*exp(-post$rhosq[i]*x) , add=TRUE , col=rangi2 )
4018
+
4019
+ # prior mean and 89% interval
4020
+ eta <- abs(rnorm(1e3,1,0.25))
4021
+ rho <- abs(rnorm(1e3,3,0.25))
4022
+ d_seq <- seq(from=0,to=1,length.out=50)
4023
+ K <- sapply( d_seq , function(x) eta*exp(-rho*x) )
4024
+ lines( d_seq , colMeans(K) , lwd=2 )
4025
+ shade( apply(K,2,PI) , d_seq )
4026
+ text( 0.5 , 0.5 , "prior" )
4027
+ text( 0.2 , 0.1 , "posterior" , col=rangi2 )
4028
+
4029
+ ## R code 14.54
4030
+ S <- matrix( c( sa^2 , sa*sb*rho , sa*sb*rho , sb^2 ) , nrow=2 )
4031
+
4032
+ ## R code 15.1
4033
+ # simulate a pancake and return randomly ordered sides
4034
+ sim_pancake <- function() {
4035
+ pancake <- sample(1:3,1)
4036
+ sides <- matrix(c(1,1,1,0,0,0),2,3)[,pancake]
4037
+ sample(sides)
4038
+ }
4039
+
4040
+ # sim 10,000 pancakes
4041
+ pancakes <- replicate( 1e4 , sim_pancake() )
4042
+ up <- pancakes[1,]
4043
+ down <- pancakes[2,]
4044
+
4045
+ # compute proportion 1/1 (BB) out of all 1/1 and 1/0
4046
+ num_11_10 <- sum( up==1 )
4047
+ num_11 <- sum( up==1 & down==1 )
4048
+ num_11/num_11_10
4049
+
4050
+ ## R code 15.2
4051
+ library(rethinking)
4052
+ data(WaffleDivorce)
4053
+ d <- WaffleDivorce
4054
+
4055
+ # points
4056
+ plot( d$Divorce ~ d$MedianAgeMarriage , ylim=c(4,15) ,
4057
+ xlab="Median age marriage" , ylab="Divorce rate" )
4058
+
4059
+ # standard errors
4060
+ for ( i in 1:nrow(d) ) {
4061
+ ci <- d$Divorce[i] + c(-1,1)*d$Divorce.SE[i]
4062
+ x <- d$MedianAgeMarriage[i]
4063
+ lines( c(x,x) , ci )
4064
+ }
4065
+
4066
+ ## R code 15.3
4067
+ dlist <- list(
4068
+ D_obs = standardize( d$Divorce ),
4069
+ D_sd = d$Divorce.SE / sd( d$Divorce ),
4070
+ M = standardize( d$Marriage ),
4071
+ A = standardize( d$MedianAgeMarriage ),
4072
+ N = nrow(d)
4073
+ )
4074
+
4075
+ m15.1 <- ulam(
4076
+ alist(
4077
+ D_obs ~ dnorm( D_true , D_sd ),
4078
+ vector[N]:D_true ~ dnorm( mu , sigma ),
4079
+ mu <- a + bA*A + bM*M,
4080
+ a ~ dnorm(0,0.2),
4081
+ bA ~ dnorm(0,0.5),
4082
+ bM ~ dnorm(0,0.5),
4083
+ sigma ~ dexp(1)
4084
+ ) , data=dlist , chains=4 , cores=4 )
4085
+
4086
+ ## R code 15.4
4087
+ precis( m15.1 , depth=2 )
4088
+
4089
+ ## R code 15.5
4090
+ dlist <- list(
4091
+ D_obs = standardize( d$Divorce ),
4092
+ D_sd = d$Divorce.SE / sd( d$Divorce ),
4093
+ M_obs = standardize( d$Marriage ),
4094
+ M_sd = d$Marriage.SE / sd( d$Marriage ),
4095
+ A = standardize( d$MedianAgeMarriage ),
4096
+ N = nrow(d)
4097
+ )
4098
+
4099
+ m15.2 <- ulam(
4100
+ alist(
4101
+ D_obs ~ dnorm( D_true , D_sd ),
4102
+ vector[N]:D_true ~ dnorm( mu , sigma ),
4103
+ mu <- a + bA*A + bM*M_true[i],
4104
+ M_obs ~ dnorm( M_true , M_sd ),
4105
+ vector[N]:M_true ~ dnorm( 0 , 1 ),
4106
+ a ~ dnorm(0,0.2),
4107
+ bA ~ dnorm(0,0.5),
4108
+ bM ~ dnorm(0,0.5),
4109
+ sigma ~ dexp( 1 )
4110
+ ) , data=dlist , chains=4 , cores=4 )
4111
+
4112
+ ## R code 15.6
4113
+ post <- extract.samples( m15.2 )
4114
+ D_true <- apply( post$D_true , 2 , mean )
4115
+ M_true <- apply( post$M_true , 2 , mean )
4116
+ plot( dlist$M_obs , dlist$D_obs , pch=16 , col=rangi2 ,
4117
+ xlab="marriage rate (std)" , ylab="divorce rate (std)" )
4118
+ points( M_true , D_true )
4119
+ for ( i in 1:nrow(d) )
4120
+ lines( c( dlist$M_obs[i] , M_true[i] ) , c( dlist$D_obs[i] , D_true[i] ) )
4121
+
4122
+ ## R code 15.7
4123
+ N <- 500
4124
+ A <- rnorm(N)
4125
+ M <- rnorm(N,-A)
4126
+ D <- rnorm(N,A)
4127
+ A_obs <- rnorm(N,A)
4128
+
4129
+ ## R code 15.8
4130
+ N <- 100
4131
+ S <- rnorm( N )
4132
+ H <- rbinom( N , size=10 , inv_logit(S) )
4133
+
4134
+ ## R code 15.9
4135
+ D <- rbern( N ) # dogs completely random
4136
+ Hm <- H
4137
+ Hm[D==1] <- NA
4138
+
4139
+ ## R code 15.10
4140
+ D <- ifelse( S > 0 , 1 , 0 )
4141
+ Hm <- H
4142
+ Hm[D==1] <- NA
4143
+
4144
+ ## R code 15.11
4145
+ set.seed(501)
4146
+ N <- 1000
4147
+ X <- rnorm(N)
4148
+ S <- rnorm(N)
4149
+ H <- rbinom( N , size=10 , inv_logit( 2 + S - 2*X ) )
4150
+ D <- ifelse( X > 1 , 1 , 0 )
4151
+ Hm <- H
4152
+ Hm[D==1] <- NA
4153
+
4154
+ ## R code 15.12
4155
+ dat_list <- list(
4156
+ H = H,
4157
+ S = S )
4158
+
4159
+ m15.3 <- ulam(
4160
+ alist(
4161
+ H ~ binomial( 10 , p ),
4162
+ logit(p) <- a + bS*S,
4163
+ a ~ normal( 0 , 1 ),
4164
+ bS ~ normal( 0 , 0.5 )
4165
+ ), data=dat_list , chains=4 )
4166
+ precis( m15.3 )
4167
+
4168
+ ## R code 15.13
4169
+ dat_list0 <- list( H = H[D==0] , S = S[D==0] )
4170
+
4171
+ m15.4 <- ulam(
4172
+ alist(
4173
+ H ~ binomial( 10 , p ),
4174
+ logit(p) <- a + bS*S,
4175
+ a ~ normal( 0 , 1 ),
4176
+ bS ~ normal( 0 , 0.5 )
4177
+ ), data=dat_list0 , chains=4 )
4178
+ precis( m15.4 )
4179
+
4180
+ ## R code 15.14
4181
+ D <- ifelse( abs(X) < 1 , 1 , 0 )
4182
+
4183
+ ## R code 15.15
4184
+ N <- 100
4185
+ S <- rnorm(N)
4186
+ H <- rbinom( N , size=10 , inv_logit(S) )
4187
+ D <- ifelse( H < 5 , 1 , 0 )
4188
+ Hm <- H; Hm[D==1] <- NA
4189
+
4190
+ ## R code 15.16
4191
+ library(rethinking)
4192
+ data(milk)
4193
+ d <- milk
4194
+ d$neocortex.prop <- d$neocortex.perc / 100
4195
+ d$logmass <- log(d$mass)
4196
+ dat_list <- list(
4197
+ K = standardize( d$kcal.per.g ),
4198
+ B = standardize( d$neocortex.prop ),
4199
+ M = standardize( d$logmass ) )
4200
+
4201
+ ## R code 15.17
4202
+ m15.5 <- ulam(
4203
+ alist(
4204
+ K ~ dnorm( mu , sigma ),
4205
+ mu <- a + bB*B + bM*M,
4206
+ B ~ dnorm( nu , sigma_B ),
4207
+ c(a,nu) ~ dnorm( 0 , 0.5 ),
4208
+ c(bB,bM) ~ dnorm( 0, 0.5 ),
4209
+ sigma_B ~ dexp( 1 ),
4210
+ sigma ~ dexp( 1 )
4211
+ ) , data=dat_list , chains=4 , cores=4 )
4212
+
4213
+ ## R code 15.18
4214
+ precis( m15.5 , depth=2 )
4215
+
4216
+ ## R code 15.19
4217
+ obs_idx <- which( !is.na(d$neocortex.prop) )
4218
+ dat_list_obs <- list(
4219
+ K = dat_list$K[obs_idx],
4220
+ B = dat_list$B[obs_idx],
4221
+ M = dat_list$M[obs_idx] )
4222
+ m15.6 <- ulam(
4223
+ alist(
4224
+ K ~ dnorm( mu , sigma ),
4225
+ mu <- a + bB*B + bM*M,
4226
+ B ~ dnorm( nu , sigma_B ),
4227
+ c(a,nu) ~ dnorm( 0 , 0.5 ),
4228
+ c(bB,bM) ~ dnorm( 0, 0.5 ),
4229
+ sigma_B ~ dexp( 1 ),
4230
+ sigma ~ dexp( 1 )
4231
+ ) , data=dat_list_obs , chains=4 , cores=4 )
4232
+ precis( m15.6 )
4233
+
4234
+ ## R code 15.20
4235
+ plot( coeftab(m15.5,m15.6) , pars=c("bB","bM") )
4236
+
4237
+ ## R code 15.21
4238
+ post <- extract.samples( m15.5 )
4239
+ B_impute_mu <- apply( post$B_impute , 2 , mean )
4240
+ B_impute_ci <- apply( post$B_impute , 2 , PI )
4241
+
4242
+ # B vs K
4243
+ plot( dat_list$B , dat_list$K , pch=16 , col=rangi2 ,
4244
+ xlab="neocortex percent (std)" , ylab="kcal milk (std)" )
4245
+ miss_idx <- which( is.na(dat_list$B) )
4246
+ Ki <- dat_list$K[miss_idx]
4247
+ points( B_impute_mu , Ki )
4248
+ for ( i in 1:12 ) lines( B_impute_ci[,i] , rep(Ki[i],2) )
4249
+
4250
+ # M vs B
4251
+ plot( dat_list$M , dat_list$B , pch=16 , col=rangi2 ,
4252
+ ylab="neocortex percent (std)" , xlab="log body mass (std)" )
4253
+ Mi <- dat_list$M[miss_idx]
4254
+ points( Mi , B_impute_mu )
4255
+ for ( i in 1:12 ) lines( rep(Mi[i],2) , B_impute_ci[,i] )
4256
+
4257
+ ## R code 15.22
4258
+ m15.7 <- ulam(
4259
+ alist(
4260
+ # K as function of B and M
4261
+ K ~ dnorm( mu , sigma ),
4262
+ mu <- a + bB*B_merge + bM*M,
4263
+
4264
+ # M and B correlation
4265
+ MB ~ multi_normal( c(muM,muB) , Rho_BM , Sigma_BM ),
4266
+ matrix[29,2]:MB <<- append_col( M , B_merge ),
4267
+
4268
+ # define B_merge as mix of observed and imputed values
4269
+ vector[29]:B_merge <- merge_missing( B , B_impute ),
4270
+
4271
+ # priors
4272
+ c(a,muB,muM) ~ dnorm( 0 , 0.5 ),
4273
+ c(bB,bM) ~ dnorm( 0, 0.5 ),
4274
+ sigma ~ dexp( 1 ),
4275
+ Rho_BM ~ lkj_corr(2),
4276
+ Sigma_BM ~ dexp(1)
4277
+ ) , data=dat_list , chains=4 , cores=4 )
4278
+ precis( m15.7 , depth=3 , pars=c("bM","bB","Rho_BM" ) )
4279
+
4280
+ ## R code 15.23
4281
+ B_missidx <- which( is.na( dat_list$B ) )
4282
+
4283
+ ## R code 15.24
4284
+ data(Moralizing_gods)
4285
+ str(Moralizing_gods)
4286
+
4287
+ ## R code 15.25
4288
+ table( Moralizing_gods$moralizing_gods , useNA="always" )
4289
+
4290
+ ## R code 15.26
4291
+ symbol <- ifelse( Moralizing_gods$moralizing_gods==1 , 16 , 1 )
4292
+ symbol <- ifelse( is.na(Moralizing_gods$moralizing_gods) , 4 , symbol )
4293
+ color <- ifelse( is.na(Moralizing_gods$moralizing_gods) , "black" , rangi2 )
4294
+ plot( Moralizing_gods$year , Moralizing_gods$population , pch=symbol ,
4295
+ col=color , xlab="Time (year)" , ylab="Population size" , lwd=1.5 )
4296
+
4297
+ ## R code 15.27
4298
+ with( Moralizing_gods ,
4299
+ table( gods=moralizing_gods , literacy=writing , useNA="always" ) )
4300
+
4301
+ ## R code 15.28
4302
+ haw <- which( Moralizing_gods$polity=="Big Island Hawaii" )
4303
+ columns <- c("year","writing","moralizing_gods")
4304
+ t( Moralizing_gods[ haw , columns ] )
4305
+
4306
+ ## R code 15.29
4307
+ set.seed(9)
4308
+ N_houses <- 100L
4309
+ alpha <- 5
4310
+ beta <- (-3)
4311
+ k <- 0.5
4312
+ r <- 0.2
4313
+ cat <- rbern( N_houses , k )
4314
+ notes <- rpois( N_houses , alpha + beta*cat )
4315
+ R_C <- rbern( N_houses , r )
4316
+ cat_obs <- cat
4317
+ cat_obs[R_C==1] <- (-9L)
4318
+ dat <- list(
4319
+ notes = notes,
4320
+ cat = cat_obs,
4321
+ RC = R_C,
4322
+ N = as.integer(N_houses) )
4323
+
4324
+ ## R code 15.30
4325
+ m15.8 <- ulam(
4326
+ alist(
4327
+ # singing bird model
4328
+ ## cat known present/absent:
4329
+ notes|RC==0 ~ poisson( lambda ),
4330
+ log(lambda) <- a + b*cat,
4331
+ ## cat NA:
4332
+ notes|RC==1 ~ custom( log_sum_exp(
4333
+ log(k) + poisson_lpmf( notes | exp(a + b) ),
4334
+ log(1-k) + poisson_lpmf( notes | exp(a) )
4335
+ ) ),
4336
+
4337
+ # priors
4338
+ a ~ normal(0,1),
4339
+ b ~ normal(0,0.5),
4340
+
4341
+ # sneaking cat model
4342
+ cat|RC==0 ~ bernoulli(k),
4343
+ k ~ beta(2,2)
4344
+ ), data=dat , chains=4 , cores=4 )
4345
+
4346
+ ## R code 15.31
4347
+ m15.9 <- ulam(
4348
+ alist(
4349
+ # singing bird model
4350
+ notes|RC==0 ~ poisson( lambda ),
4351
+ notes|RC==1 ~ custom( log_sum_exp(
4352
+ log(k) + poisson_lpmf( notes | exp(a + b) ),
4353
+ log(1-k) + poisson_lpmf( notes | exp(a) )
4354
+ ) ),
4355
+ log(lambda) <- a + b*cat,
4356
+ a ~ normal(0,1),
4357
+ b ~ normal(0,0.5),
4358
+
4359
+ # sneaking cat model
4360
+ cat|RC==0 ~ bernoulli(k),
4361
+ k ~ beta(2,2),
4362
+
4363
+ # imputed values
4364
+ gq> vector[N]:PrC1 <- exp(lpC1)/(exp(lpC1)+exp(lpC0)),
4365
+ gq> vector[N]:lpC1 <- log(k) + poisson_lpmf( notes[i] | exp(a+b) ),
4366
+ gq> vector[N]:lpC0 <- log(1-k) + poisson_lpmf( notes[i] | exp(a) )
4367
+ ), data=dat , chains=4 , cores=4 )
4368
+
4369
+ ## R code 15.32
4370
+ set.seed(100)
4371
+ x <- c( rnorm(10) , NA )
4372
+ y <- c( rnorm(10,x) , 100 )
4373
+ d <- list(x=x,y=y)
4374
+
4375
+ ## R code 15.33
4376
+ ## R code 15.34
4377
+ ## R code 15.35
4378
+ ## R code 15.36
4379
+ ## R code 15.37
4380
+ ## R code 15.38
4381
+ ## R code 15.39
4382
+ ## R code 16.1
4383
+ library(rethinking)
4384
+ data(Howell1)
4385
+ d <- Howell1
4386
+
4387
+ # scale observed variables
4388
+ d$w <- d$weight / mean(d$weight)
4389
+ d$h <- d$height / mean(d$height)
4390
+
4391
+ ## R code 16.2
4392
+ m16.1 <- ulam(
4393
+ alist(
4394
+ w ~ dlnorm( mu , sigma ),
4395
+ exp(mu) <- 3.141593 * k * p^2 * h^3,
4396
+ p ~ beta( 2 , 18 ),
4397
+ k ~ exponential( 0.5 ),
4398
+ sigma ~ exponential( 1 )
4399
+ ), data=d , chains=4 , cores=4 )
4400
+
4401
+ ## R code 16.3
4402
+ h_seq <- seq( from=0 , to=max(d$h) , length.out=30 )
4403
+ w_sim <- sim( m16.1 , data=list(h=h_seq) )
4404
+ mu_mean <- apply( w_sim , 2 , mean )
4405
+ w_CI <- apply( w_sim , 2 , PI )
4406
+ plot( d$h , d$w , xlim=c(0,max(d$h)) , ylim=c(0,max(d$w)) , col=rangi2 ,
4407
+ lwd=2 , xlab="height (scaled)" , ylab="weight (scaled)" )
4408
+ lines( h_seq , mu_mean )
4409
+ shade( w_CI , h_seq )
4410
+
4411
+ ## R code 16.4
4412
+ library(rethinking)
4413
+ data(Boxes)
4414
+ precis(Boxes)
4415
+
4416
+ ## R code 16.5
4417
+ table( Boxes$y ) / length( Boxes$y )
4418
+
4419
+ ## R code 16.6
4420
+ set.seed(7)
4421
+ N <- 30 # number of children
4422
+
4423
+ # half are random
4424
+ # sample from 1,2,3 at random for each
4425
+ y1 <- sample( 1:3 , size=N/2 , replace=TRUE )
4426
+
4427
+ # half follow majority
4428
+ y2 <- rep( 2 , N/2 )
4429
+
4430
+ # combine and shuffle y1 and y2
4431
+ y <- sample( c(y1,y2) )
4432
+
4433
+ # count the 2s
4434
+ sum(y==2)/N
4435
+
4436
+ ## R code 16.7
4437
+ data(Boxes_model)
4438
+ cat(Boxes_model)
4439
+
4440
+ ## R code 16.8
4441
+ # prep data
4442
+ dat_list <- list(
4443
+ N = nrow(Boxes),
4444
+ y = Boxes$y,
4445
+ majority_first = Boxes$majority_first )
4446
+
4447
+ # run the sampler
4448
+ m16.2 <- stan( model_code=Boxes_model , data=dat_list , chains=3 , cores=3 )
4449
+
4450
+ # show marginal posterior for p
4451
+ p_labels <- c("1 Majority","2 Minority","3 Maverick","4 Random",
4452
+ "5 Follow First")
4453
+ plot( precis(m16.2,2) , labels=p_labels )
4454
+
4455
+ ## R code 16.9
4456
+ library(rethinking)
4457
+ data(Panda_nuts)
4458
+
4459
+ ## R code 16.10
4460
+ N <- 1e4
4461
+ phi <- rlnorm( N , log(1) , 0.1 )
4462
+ k <- rlnorm( N , log(2), 0.25 )
4463
+ theta <- rlnorm( N , log(5) , 0.25 )
4464
+
4465
+ # relative grow curve
4466
+ plot( NULL , xlim=c(0,1.5) , ylim=c(0,1) , xaxt="n" , xlab="age" ,
4467
+ ylab="body mass" )
4468
+ at <- c(0,0.25,0.5,0.75,1,1.25,1.5)
4469
+ axis( 1 , at=at , labels=round(at*max(Panda_nuts$age)) )
4470
+ for ( i in 1:20 ) curve( (1-exp(-k[i]*x)) , add=TRUE , col=grau() , lwd=1.5 )
4471
+
4472
+ # implied rate of nut opening curve
4473
+ plot( NULL , xlim=c(0,1.5) , ylim=c(0,1.2) , xaxt="n" , xlab="age" ,
4474
+ ylab="nuts per second" )
4475
+ at <- c(0,0.25,0.5,0.75,1,1.25,1.5)
4476
+ axis( 1 , at=at , labels=round(at*max(Panda_nuts$age)) )
4477
+ for ( i in 1:20 ) curve( phi[i]*(1-exp(-k[i]*x))^theta[i] , add=TRUE ,
4478
+ col=grau() , lwd=1.5 )
4479
+
4480
+ ## R code 16.11
4481
+ dat_list <- list(
4482
+ n = as.integer( Panda_nuts$nuts_opened ),
4483
+ age = Panda_nuts$age / max(Panda_nuts$age),
4484
+ seconds = Panda_nuts$seconds )
4485
+
4486
+ m16.4 <- ulam(
4487
+ alist(
4488
+ n ~ poisson( lambda ),
4489
+ lambda <- seconds*phi*(1-exp(-k*age))^theta,
4490
+ phi ~ lognormal( log(1) , 0.1 ),
4491
+ k ~ lognormal( log(2) , 0.25 ),
4492
+ theta ~ lognormal( log(5) , 0.25 )
4493
+ ), data=dat_list , chains=4 )
4494
+
4495
+ ## R code 16.12
4496
+ post <- extract.samples(m16.4)
4497
+ plot( NULL , xlim=c(0,1) , ylim=c(0,1.5) , xlab="age" ,
4498
+ ylab="nuts per second" , xaxt="n" )
4499
+ at <- c(0,0.25,0.5,0.75,1,1.25,1.5)
4500
+ axis( 1 , at=at , labels=round(at*max(Panda_nuts$age)) )
4501
+
4502
+ # raw data
4503
+ pts <- dat_list$n / dat_list$seconds
4504
+ point_size <- normalize( dat_list$seconds )
4505
+ points( jitter(dat_list$age) , pts , col=rangi2 , lwd=2 , cex=point_size*3 )
4506
+
4507
+ # 30 posterior curves
4508
+ for ( i in 1:30 ) with( post ,
4509
+ curve( phi[i]*(1-exp(-k[i]*x))^theta[i] , add=TRUE , col=grau() ) )
4510
+
4511
+ ## R code 16.13
4512
+ library(rethinking)
4513
+ data(Lynx_Hare)
4514
+ plot( 1:21 , Lynx_Hare[,3] , ylim=c(0,90) , xlab="year" ,
4515
+ ylab="thousands of pelts" , xaxt="n" , type="l" , lwd=1.5 )
4516
+ at <- c(1,11,21)
4517
+ axis( 1 , at=at , labels=Lynx_Hare$Year[at] )
4518
+ lines( 1:21 , Lynx_Hare[,2] , lwd=1.5 , col=rangi2 )
4519
+ points( 1:21 , Lynx_Hare[,3] , bg="black" , col="white" , pch=21 , cex=1.4 )
4520
+ points( 1:21 , Lynx_Hare[,2] , bg=rangi2 , col="white" , pch=21 , cex=1.4 )
4521
+ text( 17 , 80 , "Lepus" , pos=2 )
4522
+ text( 19 , 50 , "Lynx" , pos=2 , col=rangi2 )
4523
+
4524
+ ## R code 16.14
4525
+ sim_lynx_hare <- function( n_steps , init , theta , dt=0.002 ) {
4526
+ L <- rep(NA,n_steps)
4527
+ H <- rep(NA,n_steps)
4528
+ L[1] <- init[1]
4529
+ H[1] <- init[2]
4530
+ for ( i in 2:n_steps ) {
4531
+ H[i] <- H[i-1] + dt*H[i-1]*( theta[1] - theta[2]*L[i-1] )
4532
+ L[i] <- L[i-1] + dt*L[i-1]*( theta[3]*H[i-1] - theta[4] )
4533
+ }
4534
+ return( cbind(L,H) )
4535
+ }
4536
+
4537
+ ## R code 16.15
4538
+ theta <- c( 0.5 , 0.05 , 0.025 , 0.5 )
4539
+ z <- sim_lynx_hare( 1e4 , as.numeric(Lynx_Hare[1,2:3]) , theta )
4540
+
4541
+ plot( z[,2] , type="l" , ylim=c(0,max(z[,2])) , lwd=2 , xaxt="n" ,
4542
+ ylab="number (thousands)" , xlab="" )
4543
+ lines( z[,1] , col=rangi2 , lwd=2 )
4544
+ mtext( "time" , 1 )
4545
+
4546
+ ## R code 16.16
4547
+ N <- 1e4
4548
+ Ht <- 1e4
4549
+ p <- rbeta(N,2,18)
4550
+ h <- rbinom( N , size=Ht , prob=p )
4551
+ h <- round( h/1000 , 2 )
4552
+ dens( h , xlab="thousand of pelts" , lwd=2 )
4553
+
4554
+ ## R code 16.17
4555
+ data(Lynx_Hare_model)
4556
+ cat(Lynx_Hare_model)
4557
+
4558
+ ## R code 16.18
4559
+ dat_list <- list(
4560
+ N = nrow(Lynx_Hare),
4561
+ pelts = Lynx_Hare[,2:3] )
4562
+
4563
+ m16.5 <- stan( model_code=Lynx_Hare_model , data=dat_list , chains=3 ,
4564
+ cores=3 , control=list( adapt_delta=0.95 ) )
4565
+
4566
+ ## R code 16.19
4567
+ post <- extract.samples(m16.5)
4568
+ pelts <- dat_list$pelts
4569
+ plot( 1:21 , pelts[,2] , pch=16 , ylim=c(0,120) , xlab="year" ,
4570
+ ylab="thousands of pelts" , xaxt="n" )
4571
+ at <- c(1,11,21)
4572
+ axis( 1 , at=at , labels=Lynx_Hare$Year[at] )
4573
+ points( 1:21 , pelts[,1] , col=rangi2 , pch=16 )
4574
+ # 21 time series from posterior
4575
+ for ( s in 1:21 ) {
4576
+ lines( 1:21 , post$pelts_pred[s,,2] , col=col.alpha("black",0.2) , lwd=2 )
4577
+ lines( 1:21 , post$pelts_pred[s,,1] , col=col.alpha(rangi2,0.3) , lwd=2 )
4578
+ }
4579
+ # text labels
4580
+ text( 17 , 90 , "Lepus" , pos=2 )
4581
+ text( 19 , 50 , "Lynx" , pos=2 , col=rangi2 )
4582
+
4583
+ ## R code 16.20
4584
+ plot( NULL , pch=16 , xlim=c(1,21) , ylim=c(0,500) , xlab="year" ,
4585
+ ylab="thousands of animals" , xaxt="n" )
4586
+ at <- c(1,11,21)
4587
+ axis( 1 , at=at , labels=Lynx_Hare$Year[at] )
4588
+ for ( s in 1:21 ) {
4589
+ lines( 1:21 , post$pop[s,,2] , col=col.alpha("black",0.2) , lwd=2 )
4590
+ lines( 1:21 , post$pop[s,,1] , col=col.alpha(rangi2,0.4) , lwd=2 )
4591
+ }
4592
+
4593
+ ## R code 16.21
4594
+ data(Lynx_Hare)
4595
+ dat_ar1 <- list(
4596
+ L = Lynx_Hare$Lynx[2:21],
4597
+ L_lag1 = Lynx_Hare$Lynx[1:20],
4598
+ H = Lynx_Hare$Hare[2:21],
4599
+ H_lag1 = Lynx_Hare$Hare[1:20] )
4600
+