Posterior predictive checking of Normal model for Newcomb's speed of light data. See Chapter 11 in Regression and Other Stories.


Load packages

library("rprojroot")
root<-has_file(".ROS-Examples-root")$make_fix_file()
library("rstanarm")
library("ggplot2")
library("bayesplot")
theme_set(bayesplot::theme_default(base_family = "sans"))

Load Data

Simon Newcomb's measurements of the speed of light, from Stigler (1977). The data are recorded as deviations from \(24,\!800\) nanoseconds.

newcomb <- read.table(root("Newcomb/data","newcomb.txt"), header = TRUE)
head(newcomb)
    y
1  28
2  26
3  33
4  24
5  34
6 -44

Histogram of the data

hist(newcomb$y, main=NULL, ylab="", xlab="", yaxt="n", breaks=30)

Histogram of the data with bayesplot

mcmc_hist(newcomb, pars="y") + xlab("")

Fit a regression model with just the intercept term

The option refresh = 0 supresses the default Stan sampling progress output. This is useful for small data with fast computation. For more complex models and bigger data, it can be useful to see the progress.

fit <- stan_glm(y ~ 1, data=newcomb, refresh=0)

Simulate from the predictive distribution

sims <- as.matrix(fit)
n_sims <- nrow(sims)
n <- length(newcomb$y)
y_rep <- array(NA, c(n_sims, n))
for (s in 1:n_sims)
    y_rep[s,] <- rnorm(n, sims[s,1], sims[s,2])

Plot histogram of 20 replicates

par(mfrow=c(4,5), mar=rep(2,4))
for (s in sample(n_sims, 20)) {
  hist(y_rep[s,], main=NULL, ylab="", xlab="", yaxt="n") }

Simulate using built-in function

y_rep <- posterior_predict(fit)

Plot data and 19 replications using built-in function

ppc_hist(newcomb$y, y_rep[1:19, ], binwidth = 8)

Plot kernel density estimate of data and 100 replications using built-in function

ppc_dens_overlay(newcomb$y, y_rep[1:100, ]) + scale_y_continuous(breaks=NULL)

Plot test statistic for data and replicates

test <- function (y) {
  min(y) }
test_rep <- apply(y_rep, 1, test)
hist(test_rep, xlim=c(-50,20), breaks=20, yaxt="n",
     xlab="", ylab="", main=NULL)
lines(rep(test(newcomb$y),2), c(0,n_sims), lwd=3)

Plot test statistic for data and replicates using built-in function

ppc_stat(newcomb$y, y_rep, stat = "min", binwidth = 2)

LS0tCnRpdGxlOiAiUmVncmVzc2lvbiBhbmQgT3RoZXIgU3RvcmllczogTmV3Y29tYiIKYXV0aG9yOiAiQW5kcmV3IEdlbG1hbiwgSmVubmlmZXIgSGlsbCwgQWtpIFZlaHRhcmkiCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSlgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDIKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KUG9zdGVyaW9yIHByZWRpY3RpdmUgY2hlY2tpbmcgb2YgTm9ybWFsIG1vZGVsIGZvciBOZXdjb21iJ3Mgc3BlZWQKb2YgbGlnaHQgZGF0YS4gU2VlIENoYXB0ZXIgMTEgaW4gUmVncmVzc2lvbiBhbmQgT3RoZXIgU3Rvcmllcy4KCi0tLS0tLS0tLS0tLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjb21tZW50PU5BKQojIHN3aXRjaCB0aGlzIHRvIFRSVUUgdG8gc2F2ZSBmaWd1cmVzIGluIHNlcGFyYXRlIGZpbGVzCnNhdmVmaWdzIDwtIEZBTFNFCmBgYAoKIyMjIyBMb2FkIHBhY2thZ2VzCgpgYGB7ciB9CmxpYnJhcnkoInJwcm9qcm9vdCIpCnJvb3Q8LWhhc19maWxlKCIuUk9TLUV4YW1wbGVzLXJvb3QiKSRtYWtlX2ZpeF9maWxlKCkKbGlicmFyeSgicnN0YW5hcm0iKQpsaWJyYXJ5KCJnZ3Bsb3QyIikKbGlicmFyeSgiYmF5ZXNwbG90IikKdGhlbWVfc2V0KGJheWVzcGxvdDo6dGhlbWVfZGVmYXVsdChiYXNlX2ZhbWlseSA9ICJzYW5zIikpCmBgYApgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojIGdyYXlzY2FsZSBmaWd1cmVzIGZvciB0aGUgYm9vawpjb2xvcl9zY2hlbWVfc2V0KHNjaGVtZSA9ICJncmF5IikKYGBgCgojIyMjIExvYWQgRGF0YQoKU2ltb24gTmV3Y29tYidzIG1lYXN1cmVtZW50cyBvZiB0aGUgc3BlZWQgb2YgbGlnaHQsIGZyb20gU3RpZ2xlcgooMTk3NykuICBUaGUgZGF0YSBhcmUgcmVjb3JkZWQgYXMgZGV2aWF0aW9ucyBmcm9tICQyNCxcITgwMCQKbmFub3NlY29uZHMuCgpgYGB7ciB9Cm5ld2NvbWIgPC0gcmVhZC50YWJsZShyb290KCJOZXdjb21iL2RhdGEiLCJuZXdjb21iLnR4dCIpLCBoZWFkZXIgPSBUUlVFKQpoZWFkKG5ld2NvbWIpCmBgYAoKIyMjIyBIaXN0b2dyYW0gb2YgdGhlIGRhdGEKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmlmIChzYXZlZmlncykgcGRmKHJvb3QoIk5ld2NvbWIvZmlncyIsIm5ld2NvbWJfaGlzdC5wZGYiKSwgaGVpZ2h0PTQsIHdpZHRoPTUpCmBgYApgYGB7ciB9Cmhpc3QobmV3Y29tYiR5LCBtYWluPU5VTEwsIHlsYWI9IiIsIHhsYWI9IiIsIHlheHQ9Im4iLCBicmVha3M9MzApCmBgYApgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQppZiAoc2F2ZWZpZ3MpIGRldi5vZmYoKQpgYGAKCiMjIyMgSGlzdG9ncmFtIG9mIHRoZSBkYXRhIHdpdGggYmF5ZXNwbG90CgpgYGB7ciB9Cm1jbWNfaGlzdChuZXdjb21iLCBwYXJzPSJ5IikgKyB4bGFiKCIiKQpgYGAKCiMjIyMgRml0IGEgcmVncmVzc2lvbiBtb2RlbCB3aXRoIGp1c3QgdGhlIGludGVyY2VwdCB0ZXJtCgpUaGUgb3B0aW9uIGByZWZyZXNoID0gMGAgc3VwcmVzc2VzIHRoZSBkZWZhdWx0IFN0YW4gc2FtcGxpbmcKcHJvZ3Jlc3Mgb3V0cHV0LiBUaGlzIGlzIHVzZWZ1bCBmb3Igc21hbGwgZGF0YSB3aXRoIGZhc3QKY29tcHV0YXRpb24uIEZvciBtb3JlIGNvbXBsZXggbW9kZWxzIGFuZCBiaWdnZXIgZGF0YSwgaXQgY2FuIGJlCnVzZWZ1bCB0byBzZWUgdGhlIHByb2dyZXNzLgoKYGBge3IgfQpmaXQgPC0gc3Rhbl9nbG0oeSB+IDEsIGRhdGE9bmV3Y29tYiwgcmVmcmVzaD0wKQpgYGAKCiMjIyMgU2ltdWxhdGUgZnJvbSB0aGUgcHJlZGljdGl2ZSBkaXN0cmlidXRpb24KCmBgYHtyIH0Kc2ltcyA8LSBhcy5tYXRyaXgoZml0KQpuX3NpbXMgPC0gbnJvdyhzaW1zKQpuIDwtIGxlbmd0aChuZXdjb21iJHkpCnlfcmVwIDwtIGFycmF5KE5BLCBjKG5fc2ltcywgbikpCmZvciAocyBpbiAxOm5fc2ltcykKICAgIHlfcmVwW3MsXSA8LSBybm9ybShuLCBzaW1zW3MsMV0sIHNpbXNbcywyXSkKYGBgCgojIyMjIFBsb3QgaGlzdG9ncmFtIG9mIDIwIHJlcGxpY2F0ZXMKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmlmIChzYXZlZmlncykgcGRmKHJvb3QoIk5ld2NvbWIvZmlncyIsIm5ld2NvbWJfcmVwX2hpc3QucGRmIiksIGhlaWdodD00LCB3aWR0aD04KQpgYGAKYGBge3IgfQpwYXIobWZyb3c9Yyg0LDUpLCBtYXI9cmVwKDIsNCkpCmZvciAocyBpbiBzYW1wbGUobl9zaW1zLCAyMCkpIHsKICBoaXN0KHlfcmVwW3MsXSwgbWFpbj1OVUxMLCB5bGFiPSIiLCB4bGFiPSIiLCB5YXh0PSJuIikgfQpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBkZXYub2ZmKCkKYGBgCgojIyMjIFNpbXVsYXRlIHVzaW5nIGJ1aWx0LWluIGZ1bmN0aW9uCgpgYGB7ciB9CnlfcmVwIDwtIHBvc3Rlcmlvcl9wcmVkaWN0KGZpdCkKYGBgCgojIyMjIFBsb3QgZGF0YSBhbmQgMTkgcmVwbGljYXRpb25zIHVzaW5nIGJ1aWx0LWluIGZ1bmN0aW9uCgpgYGB7ciB9CnBwY19oaXN0KG5ld2NvbWIkeSwgeV9yZXBbMToxOSwgXSwgYmlud2lkdGggPSA4KQpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBnZ3NhdmUocm9vdCgiTmV3Y29tYi9maWdzIiwibmV3Y29tYl9wcGNfaGlzdC5wZGYiKSwgd2lkdGggPSA5LCBoZWlnaHQgPSA0KQpgYGAKCiMjIyMgUGxvdCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSBvZiBkYXRhIGFuZCAxMDAgcmVwbGljYXRpb25zIHVzaW5nIGJ1aWx0LWluIGZ1bmN0aW9uCgpgYGB7ciB9CnBwY19kZW5zX292ZXJsYXkobmV3Y29tYiR5LCB5X3JlcFsxOjEwMCwgXSkgKyBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPU5VTEwpCmBgYApgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQppZiAoc2F2ZWZpZ3MpIGdnc2F2ZShyb290KCJOZXdjb21iL2ZpZ3MiLCJuZXdjb21iX3BwY19kZW5zX292ZXJsYXkucGRmIiksIHdpZHRoID0gNiwgaGVpZ2h0ID0gMi41KQpgYGAKCiMjIyMgUGxvdCB0ZXN0IHN0YXRpc3RpYyBmb3IgZGF0YSBhbmQgcmVwbGljYXRlcwoKYGBge3IgfQp0ZXN0IDwtIGZ1bmN0aW9uICh5KSB7CiAgbWluKHkpIH0KdGVzdF9yZXAgPC0gYXBwbHkoeV9yZXAsIDEsIHRlc3QpCmBgYApgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQppZiAoc2F2ZWZpZ3MpIHBkZihyb290KCJOZXdjb21iL2ZpZ3MiLCJuZXdjb21iX3Rlc3RfaGlzdC5wZGYiKSwgaGVpZ2h0PTQsIHdpZHRoPTUpCmBgYApgYGB7ciB9Cmhpc3QodGVzdF9yZXAsIHhsaW09YygtNTAsMjApLCBicmVha3M9MjAsIHlheHQ9Im4iLAogICAgIHhsYWI9IiIsIHlsYWI9IiIsIG1haW49TlVMTCkKbGluZXMocmVwKHRlc3QobmV3Y29tYiR5KSwyKSwgYygwLG5fc2ltcyksIGx3ZD0zKQpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBkZXYub2ZmKCkKYGBgCgojIyMjIFBsb3QgdGVzdCBzdGF0aXN0aWMgZm9yIGRhdGEgYW5kIHJlcGxpY2F0ZXMgdXNpbmcgYnVpbHQtaW4gZnVuY3Rpb24KCmBgYHtyIH0KcHBjX3N0YXQobmV3Y29tYiR5LCB5X3JlcCwgc3RhdCA9ICJtaW4iLCBiaW53aWR0aCA9IDIpCmBgYApgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQppZiAoc2F2ZWZpZ3MpIGdnc2F2ZShyb290KCJOZXdjb21iL2ZpZ3MiLCJuZXdjb21iX3BwY19zdGF0LnBkZiIpLCB3aWR0aCA9IDYsIGhlaWdodCA9IDQpCmBgYAoK