Interactive, data-driven visualizations on static web pages

using Observable.js and Quarto

James E. Pustejovsky

2026-09-01

James E. Pustejovsky

(“PUHS-tea-UV-ski” or “Pusto” for short)

  • Full Professor in Educational Psychology, Quantitative Methods Program

  • PhD in Statistics (Northwestern University, 2013)

  • Applied statistician & methodologist

    • Main research focus is research synthesis and meta-analysis.

    • Long-time R programmer (pre-tidyverse).

    • Not a web developer or software engineer.

Observable.js

  • JavaScript dialect designed by Mike Bostock for use with browser-based Observable notebooks.

    • Created by Mike Bostock

    • Includes intuitive plotting library

    • Includes simple interactive input library

  • Quarto (.qmd) can include Observable cells as {ojs}

    • On static html pages

    • In reveal.js presentations (like this one)

  • Useful for

    • Building intuitions about statistics

    • Teaching

    • Presenting research findings

Mike Bostock

Model Fit Criteria

  • Widely used measures of model fit (AIC, DIC, WIC, LOOIC) are defined in terms of Kullback-Leibler divergence.

    • How do you interpret differences in model fit measures?

  • Suppose we have two models fit to the same data. The models differ in fit by some amount \(\Delta\).

  • One approach to interpreting is calibration

    • Find two simpler-to-conceptualize models that have the same difference in KL-divergence.

Coin flip calibration

  • Imagine you are flipping a coin \(N\) times and that you expect the coin to be fair.

    • Your mental model is that the number of heads \(H \sim Binom\left(N, \frac{1}{2}\right)\).
  • The coin is actually biased with probability of heads \(\phi\).

\[ \Delta = KL\left(Bin\left(N,\phi\right), Bin\left(N,\frac{1}{2}\right)\right) = N \times \left[\log 2 + \phi \log \phi + (1 - \phi) \log(1 - \phi)\right]. \]

Standard normal calibrations

Figure 1: Standard normal distribution (black line) that diverges by \(\Delta\) from selected non-normal distributions, including \(N(\mu, 1)\) (blue density), \(N(0,\sigma^2)\) (green density), shifted \(\Gamma(\alpha, \sqrt{\alpha})\) (orange density), or \(t(\nu)\) (red density).

Teaching statistics

An example from meta-analysis

Step-function selection models

  • The data for \(j = 1,...,J\) effect size estimates

    • \(T_{j}, \sigma_{j} \quad\) estimate and standard error for effect size \(j\)

    • \(p_{j} = \Phi^{-1}(-T_{j} / \sigma_{j}) \quad\) one-sided \(p\)-value of effect estimate \(j\)

  • Random effects model for the evidence-generating process (before selective reporting): \[T_{j} \sim N\left(\ \mu, \ \tau^2 + \sigma_{j}^2 \right)\]
  • \(H\)-step model for the selection process with steps \(\alpha_1,...,\alpha_H\) (taking \(\lambda_0 = 1, \alpha_0 = 0, \alpha_{H+1} = 1\)): \[\text{Pr}(\ T_{j} \text{ is observed} \ ) \propto \sum_{h=0}^H \lambda_h \times I(\alpha_{h} \leq p_{j} < \alpha_{H+1})\]

A piece-wise normal distribution

The step-function model implies that the distribution of observed effect size estimates is piece-wise normal.

Displaying Simulation Study Results

Simulation Design

Parameter Full Simulation Bootstrap Simulation
Overall average effect 0.0, 0.2, 0.4, 0.8 0.0, 0.2, 0.4, 0.8
Between-study heterogeneity 0.05, 0.15, 0.30, 0.45 0.05, 0.45
Within-study heterogeneity ratio 0.0, 0.5 0.0, 0.5
Correlation between outcomes 0.4, 0.8 0.8
Selection probability 0.02, 0.05, 0.10, 0.20, 0.50, 1.00 0.05, 0.20, 1.00
Number of primary studies 15, 30, 60, 90, 120 15, 30, 60
Primary study sample sizes Typical, Small Typical, Small
  • 2000 replications per condition

  • 399 bootstraps per replication

Bias for mean effect size \((\mu)\)

Accuracy for mean effect size \((\mu)\)

Coverage rates of large-sample (sandwich) CIs

Bias for mean effect size \((\mu)\)

Accuracy for mean effect size \((\mu)\)

Coverage rates of 95% CIs for \(\mu\)

Programming tips

  • Use ObservableHQ.com online notebooks to template interactive graphics.

  • In Quarto, pass data from R to Observable with ojs_define()