Posterior predictive checking of normal model for light data
ggplot2 and bayesplot are used for plotting tidyr is used for manipulating data frames posterior is used to handle posterior draws
library(ggplot2)
library(bayesplot)
theme_set(bayesplot::theme_default(base_family = "sans"))
library(posterior)
library(tidyr)
library(latex2exp)
library(rprojroot)
root<-has_file(".BDA_R_demos_root")$make_fix_file()
Data
y <- read.table(root("demos_ch6","light.txt"))$V1
Sufficient statistics
n <- length(y)
s <- sd(y)
my <- mean(y)
Create 9 random replicate data sets from the posterior predictive density. Each set has same number of virtual observations as the original data set.
yrep <- replicate(9, rt(n, n-1)*sqrt(1+1/n)*s+my)
Replace one of the replicates with observed data. If you can spot which one has been replaced, it means that the replicates do not resemble the original data and thus the model has a defect
ind <- sample(9, 1)
yrep_df <- yrep %>%
as.data.frame() %>%
replace(ind, y) %>% # replace one of the yreps
setNames(1:9) %>% # rename to hide which one is the real data
pivot_longer(everything()) # use the long format for plotting
ggplot(data = yrep_df) +
geom_histogram(aes(x = value), fill = 'steelblue',
color = 'black', binwidth = 4) +
facet_wrap(~name, nrow = 3) +
coord_cartesian(xlim = c(-55, 65)) +
labs(x = '', y = '') +
scale_y_continuous(breaks=NULL) +
theme(strip.background = element_blank())
Generate 1000 replicate data sets and compute test statistic. The test statistic here is the smallest observation in the data or in the replicated data.
yrep1000 <- replicate(1000, rt(n, n-1)*sqrt(1+1/n)*s+my) %>%
as.data.frame()
# the minimum value over 1000 replicates
minvals <- data.frame(x = sapply(yrep1000, min))
Plot test statistic for the data and the replicated data sets
title1 <- 'Smallest observation in the replicated
data (hist.) vs in the original data (vertical line)'
ggplot(data = minvals) +
geom_histogram(aes(x = x), fill = 'steelblue',
color = 'black', binwidth = 2) +
geom_vline(aes(xintercept = min(x)), data = data.frame(x = y),
color = 'red') +
coord_cartesian(xlim = c(-50, 20)) +
labs(x = TeX('Minimum of \\textit{y} and \\textit{y}$^{rep}$'),
y = '', title = title1) +
scale_y_continuous(breaks=NULL)
Posterior predictive checks provided by bayesplot
https://mc-stan.org/bayesplot/reference/PPC-distributions.html
For convenience switch to use draws object
rownames(yrep1000) <- paste0("yrep[", 1:66, "]")
yrep_draws <- as_draws_matrix(t(yrep1000))
Histogram of y + 8 yrep histograms
ppc_hist(y, yrep_draws[1:8,])
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Kernel density estimate of y + 100 yrep kernel density estimates
ppc_dens_overlay(y, yrep_draws[1:100,])
ECDF of y + 100 yrep ECDFs
ppc_ecdf_overlay(y, yrep_draws[1:100,])
Scatterplot of yrep vs y
ppc_scatter(y, yrep_draws[1:4,])+geom_abline()
The distribution of a (test) statistic T(yrep) compared to the observed value T(y) computed from the data y. The default test statistic mean is a bad statistic as the model has a parameter for the mean.
ppc_stat(y, yrep_draws)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
The distribution of a (test) statistic T(yrep) compared to the observed value T(y) computed from the data y. Min and max are often good test statistics for continuous outcomes.
ppc_stat(y, yrep_draws, stat="min")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
ppc_stat(y, yrep_draws, stat="max")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Show 2 test statistics in one plot
color_scheme_set("brewer-Paired")
ppc_stat_2d(y, yrep_draws, stat=c("min","max"))
color_scheme_set()
LS0tCnRpdGxlOiAiQmF5ZXNpYW4gZGF0YSBhbmFseXNpcyBkZW1vIDYuMSIKYXV0aG9yOiAiQWtpIFZlaHRhcmksIE1hcmt1cyBQYWFzaW5pZW1pIgpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCkpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogcmVhZGFibGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCiMjIFBvc3RlcmlvciBwcmVkaWN0aXZlIGNoZWNraW5nIG9mIG5vcm1hbCBtb2RlbCBmb3IgbGlnaHQgZGF0YQoKZ2dwbG90MiBhbmQgYmF5ZXNwbG90IGFyZSB1c2VkIGZvciBwbG90dGluZwp0aWR5ciBpcyB1c2VkIGZvciBtYW5pcHVsYXRpbmcgZGF0YSBmcmFtZXMKcG9zdGVyaW9yIGlzIHVzZWQgdG8gaGFuZGxlIHBvc3RlcmlvciBkcmF3cwoKYGBge3Igc2V0dXAsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoYmF5ZXNwbG90KQp0aGVtZV9zZXQoYmF5ZXNwbG90Ojp0aGVtZV9kZWZhdWx0KGJhc2VfZmFtaWx5ID0gInNhbnMiKSkKbGlicmFyeShwb3N0ZXJpb3IpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkobGF0ZXgyZXhwKQpsaWJyYXJ5KHJwcm9qcm9vdCkKcm9vdDwtaGFzX2ZpbGUoIi5CREFfUl9kZW1vc19yb290IikkbWFrZV9maXhfZmlsZSgpCmBgYAoKRGF0YQoKYGBge3IgfQp5IDwtIHJlYWQudGFibGUocm9vdCgiZGVtb3NfY2g2IiwibGlnaHQudHh0IikpJFYxCmBgYAoKU3VmZmljaWVudCBzdGF0aXN0aWNzCgpgYGB7ciB9Cm4gPC0gbGVuZ3RoKHkpCnMgPC0gc2QoeSkKbXkgPC0gbWVhbih5KQpgYGAKCkNyZWF0ZSA5IHJhbmRvbSByZXBsaWNhdGUgZGF0YSBzZXRzIGZyb20gdGhlIHBvc3RlcmlvcgpwcmVkaWN0aXZlIGRlbnNpdHkuCkVhY2ggc2V0IGhhcyBzYW1lIG51bWJlciBvZiB2aXJ0dWFsIG9ic2VydmF0aW9ucyBhcyB0aGUKb3JpZ2luYWwgZGF0YSBzZXQuCgpgYGB7ciB9CnlyZXAgPC0gcmVwbGljYXRlKDksIHJ0KG4sIG4tMSkqc3FydCgxKzEvbikqcytteSkKYGBgCgpSZXBsYWNlIG9uZSBvZiB0aGUgcmVwbGljYXRlcyB3aXRoIG9ic2VydmVkIGRhdGEuCklmIHlvdSBjYW4gc3BvdCB3aGljaCBvbmUgaGFzIGJlZW4gcmVwbGFjZWQsIGl0IG1lYW5zCnRoYXQgdGhlIHJlcGxpY2F0ZXMgZG8gbm90IHJlc2VtYmxlIHRoZSBvcmlnaW5hbCBkYXRhCmFuZCB0aHVzIHRoZSBtb2RlbCBoYXMgYSBkZWZlY3QKCmBgYHtyIH0KaW5kIDwtIHNhbXBsZSg5LCAxKQp5cmVwX2RmIDwtIHlyZXAgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JQogIHJlcGxhY2UoaW5kLCB5KSAlPiUgIyByZXBsYWNlIG9uZSBvZiB0aGUgeXJlcHMKICBzZXROYW1lcygxOjkpICU+JSAgICMgcmVuYW1lIHRvIGhpZGUgd2hpY2ggb25lIGlzIHRoZSByZWFsIGRhdGEKICBwaXZvdF9sb25nZXIoZXZlcnl0aGluZygpKSAjIHVzZSB0aGUgbG9uZyBmb3JtYXQgZm9yIHBsb3R0aW5nCgpnZ3Bsb3QoZGF0YSA9IHlyZXBfZGYpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IHZhbHVlKSwgZmlsbCA9ICdzdGVlbGJsdWUnLAogICAgICAgICAgICAgICAgIGNvbG9yID0gJ2JsYWNrJywgYmlud2lkdGggPSA0KSArCiAgZmFjZXRfd3JhcCh+bmFtZSwgbnJvdyA9IDMpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTU1LCA2NSkpICsKICBsYWJzKHggPSAnJywgeSA9ICcnKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1OVUxMKSArCiAgdGhlbWUoc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgpHZW5lcmF0ZSAxMDAwIHJlcGxpY2F0ZSBkYXRhIHNldHMgYW5kIGNvbXB1dGUgdGVzdCBzdGF0aXN0aWMuIFRoZQp0ZXN0IHN0YXRpc3RpYyBoZXJlIGlzIHRoZSBzbWFsbGVzdCBvYnNlcnZhdGlvbiBpbiB0aGUgZGF0YSBvciBpbgp0aGUgcmVwbGljYXRlZCBkYXRhLgoKYGBge3IgfQp5cmVwMTAwMCA8LSByZXBsaWNhdGUoMTAwMCwgcnQobiwgbi0xKSpzcXJ0KDErMS9uKSpzK215KSAlPiUKICBhcy5kYXRhLmZyYW1lKCkKIyB0aGUgbWluaW11bSB2YWx1ZSBvdmVyIDEwMDAgcmVwbGljYXRlcwptaW52YWxzIDwtIGRhdGEuZnJhbWUoeCA9IHNhcHBseSh5cmVwMTAwMCwgbWluKSkKYGBgCgpQbG90IHRlc3Qgc3RhdGlzdGljIGZvciB0aGUgZGF0YSBhbmQgdGhlIHJlcGxpY2F0ZWQgZGF0YSBzZXRzCgpgYGB7ciB9CnRpdGxlMSA8LSAnU21hbGxlc3Qgb2JzZXJ2YXRpb24gaW4gdGhlIHJlcGxpY2F0ZWQKZGF0YSAoaGlzdC4pIHZzIGluIHRoZSBvcmlnaW5hbCBkYXRhICh2ZXJ0aWNhbCBsaW5lKScKZ2dwbG90KGRhdGEgPSBtaW52YWxzKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSB4KSwgZmlsbCA9ICdzdGVlbGJsdWUnLAogICAgICAgICAgICAgICAgIGNvbG9yID0gJ2JsYWNrJywgYmlud2lkdGggPSAyKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1pbih4KSksIGRhdGEgPSBkYXRhLmZyYW1lKHggPSB5KSwKICAgICAgICAgICAgIGNvbG9yID0gJ3JlZCcpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTUwLCAyMCkpICsKICBsYWJzKHggPSBUZVgoJ01pbmltdW0gb2YgXFx0ZXh0aXR7eX0gYW5kIFxcdGV4dGl0e3l9JF57cmVwfSQnKSwKICAgICAgIHkgPSAnJywgdGl0bGUgPSB0aXRsZTEpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPU5VTEwpCmBgYAoKUG9zdGVyaW9yIHByZWRpY3RpdmUgY2hlY2tzIHByb3ZpZGVkIGJ5IGJheWVzcGxvdDxicj4KaHR0cHM6Ly9tYy1zdGFuLm9yZy9iYXllc3Bsb3QvcmVmZXJlbmNlL1BQQy1kaXN0cmlidXRpb25zLmh0bWwKCkZvciBjb252ZW5pZW5jZSBzd2l0Y2ggdG8gdXNlIGRyYXdzIG9iamVjdAoKYGBge3IgfQpyb3duYW1lcyh5cmVwMTAwMCkgPC0gcGFzdGUwKCJ5cmVwWyIsIDE6NjYsICJdIikKeXJlcF9kcmF3cyA8LSBhc19kcmF3c19tYXRyaXgodCh5cmVwMTAwMCkpCmBgYAoKSGlzdG9ncmFtIG9mIHkgKyA4IHlyZXAgaGlzdG9ncmFtcwoKYGBge3IgfQpwcGNfaGlzdCh5LCB5cmVwX2RyYXdzWzE6OCxdKQpgYGAKCktlcm5lbCBkZW5zaXR5IGVzdGltYXRlIG9mIHkgKyAxMDAgeXJlcCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZXMKCmBgYHtyIH0KcHBjX2RlbnNfb3ZlcmxheSh5LCB5cmVwX2RyYXdzWzE6MTAwLF0pCmBgYAoKRUNERiBvZiB5ICsgMTAwIHlyZXAgRUNERnMKCmBgYHtyIH0KcHBjX2VjZGZfb3ZlcmxheSh5LCB5cmVwX2RyYXdzWzE6MTAwLF0pCmBgYAoKU2NhdHRlcnBsb3Qgb2YgeXJlcCB2cyB5CgpgYGB7ciB9CnBwY19zY2F0dGVyKHksIHlyZXBfZHJhd3NbMTo0LF0pK2dlb21fYWJsaW5lKCkKYGBgCgpUaGUgZGlzdHJpYnV0aW9uIG9mIGEgKHRlc3QpIHN0YXRpc3RpYyBUKHlyZXApIGNvbXBhcmVkIHRvIHRoZQpvYnNlcnZlZCB2YWx1ZSBUKHkpIGNvbXB1dGVkIGZyb20gdGhlIGRhdGEgeS4gVGhlIGRlZmF1bHQgdGVzdApzdGF0aXN0aWMgbWVhbiBpcyBhIGJhZCBzdGF0aXN0aWMgYXMgdGhlIG1vZGVsIGhhcyBhIHBhcmFtZXRlciBmb3IKdGhlIG1lYW4uCgpgYGB7ciB9CnBwY19zdGF0KHksIHlyZXBfZHJhd3MpCmBgYAoKVGhlIGRpc3RyaWJ1dGlvbiBvZiBhICh0ZXN0KSBzdGF0aXN0aWMgVCh5cmVwKSBjb21wYXJlZCB0byB0aGUKb2JzZXJ2ZWQgdmFsdWUgVCh5KSBjb21wdXRlZCBmcm9tIHRoZSBkYXRhIHkuIE1pbiBhbmQgbWF4IGFyZSBvZnRlbgpnb29kIHRlc3Qgc3RhdGlzdGljcyBmb3IgY29udGludW91cyBvdXRjb21lcy4KCmBgYHtyIH0KcHBjX3N0YXQoeSwgeXJlcF9kcmF3cywgc3RhdD0ibWluIikKcHBjX3N0YXQoeSwgeXJlcF9kcmF3cywgc3RhdD0ibWF4IikKYGBgCgpTaG93IDIgdGVzdCBzdGF0aXN0aWNzIGluIG9uZSBwbG90CgpgYGB7ciB9CmNvbG9yX3NjaGVtZV9zZXQoImJyZXdlci1QYWlyZWQiKQpwcGNfc3RhdF8yZCh5LCB5cmVwX2RyYXdzLCBzdGF0PWMoIm1pbiIsIm1heCIpKQpjb2xvcl9zY2hlbWVfc2V0KCkKYGBgCgo=