knitr::opts_chunk$set(
echo = TRUE,
message = FALSE,
warning = FALSE,
results = "hide",
error = FALSE,
comment = ''
)
This document exists in the repository at https://github.com/codatmo/Liverpool as model_reproduction_checklist.Rmd
and rendered in html as https://github.com/codatmo/Liverpool/model_reproduction_checklist.html.
The sister page https://codatmo.github.io/Liverpool/index.html describes the model more fully.
This model is part of the CoDatMo (Co)vid (Dat)a (Mo)deling site (https://codatmo.github.io/) which is intended to replicate and make available important COVID models written in Bayesian modeling languages like Stan or PyMC3.
Model goal is to estimate COVID hospitalizations based on reports from 111 calls to government services and/or website reports.
See https://codatmo.github.io/Liverpool/index.html for detailed description.
Actual data is available as described at https://codatmo.github.io/Data/index.html. An .RDS file exists locally at nhs_regions_111_calls.RDS
.
calls_111.df <- readRDS("data/nhs_regions_111_calls.Rds")
deaths.df <- readRDS("data/nhs_regions_deaths.Rds")
calls_111 <- as.numeric(calls_111.df$London[1:71])
deaths <- as.numeric(deaths.df$London[1:14])
There is a script to generate simulated data.
source("src/scripts/generateSimulatedData.R")
generatedData <- generateSimulatedData(
seed = 0,
maxTime = 100,
population = 1000000,
n_beta_pieces = 20,
n_rho_calls_111_pieces = 10,
calls_111_start = 30
)
stan_data_sim <- generatedData$stan_data
stan_data_sim$compute_likelihood <- 1 # controls whether likelihood is computed
ground_truth_sim <- generatedData$ground_truth
The script does a fair amount of data munging, see below, but the data analogous to production data are two data sources:
#deaths <- stan_data$deaths
#calls_111 <- stan_data$calls_111
cat(paste(sprintf("Weekly COVID death count=%d, Days of 111_calls (7 days per weekly count)=%d",
length(deaths),
length(calls_111))))
Weekly COVID death count=14, Days of 111_calls (7 days per weekly count)=71
library(ggplot2)
library(tidyr)
library(gridExtra)
day <- 1:length(calls_111)
data.df <- data.frame(calls_111,day)
data.df$deaths <- ifelse(data.df$day %% 7 == 0, deaths[data.df$day %/% 7], NA)
ggplot(data.df) +
aes(x=1:length(calls_111), y=calls_111) +
geom_line() -> p1
ggplot(data.df) +
aes(x=1:length(calls_111), y=deaths) +
geom_point() -> p2
grid.arrange(p1, p2, ncol=2)
The data undergo considerable processing before being ready to fit with Stan. There are 22 data parameters of which two are the deaths
and calls_111
shown above. The data elaboration proceeds as follows:
# deaths <- stan_data$deaths
# calls_111 <- stan_data$calls_111
# below are constants
T <- 100
maxTime <- T
initial_time <- 0
n_disease_states <- 8
n_beta_pieces <- 20
calls_111_start <- 30
n_rho_calls_111_pieces <- 10
population <- 1e+06
beta_pieceLength <- ceiling(maxTime / n_beta_pieces)
beta_left_t <- seq(0, maxTime - 1, by = beta_pieceLength)
beta_right_t <- c(beta_left_t[2:n_beta_pieces], maxTime + 1)
real_data_length = length(beta_left_t) + length(beta_right_t) + 1
real_data = c(beta_left_t, beta_right_t, population)
integer_data = c(
maxTime,
length(beta_left_t),
length(beta_right_t),
length(beta_left_t),
n_disease_states
)
integer_data_length <- length(integer_data)
rho_calls_pieceLength <-
ceiling((maxTime - calls_111_start) / n_rho_calls_111_pieces)
rho_calls_111_left_t <-
seq(calls_111_start, maxTime - 1, by = rho_calls_pieceLength)
rho_calls_111_right_t <-
c(rho_calls_111_left_t[2:n_rho_calls_111_pieces], maxTime + 1)
times <- 1:T
deaths_length <- length(deaths)
deaths_starts <- seq(from = 1, to = deaths_length * 7, by = 7)
deaths_stops <- seq(from = 7, to = deaths_length * 7, by = 7)
calls_111_length <- length(calls_111)
stan_data <- list(
initial_time = initial_time,
n_beta_pieces = n_beta_pieces,
beta_left_t = beta_left_t,
beta_right_t = beta_right_t,
T = maxTime,
times = times,
n_disease_states = n_disease_states,
population = population,
deaths_length = length(deaths),
deaths_starts = deaths_starts,
deaths_stops = deaths_stops,
deaths = deaths,
real_data_length = length(beta_left_t) + length(beta_right_t) + 1,
real_data = c(beta_left_t, beta_right_t, population),
integer_data_length = 5,
integer_data = c(
maxTime,
length(beta_left_t),
length(beta_right_t),
length(beta_left_t),
n_disease_states
),
n_rho_calls_111_pieces = n_rho_calls_111_pieces,
rho_calls_111_left_t = rho_calls_111_left_t,
rho_calls_111_right_t = rho_calls_111_right_t,
calls_111_start = calls_111_start,
calls_111 = calls_111,
calls_111_length = calls_111_length,
compute_likelihood = 1
)
# test that data has been properly munged.
# for (varname in names(stan_data)) {
# # print(paste("trying:",varname))
# if (!varname %in% names(stan_data2)) {
# print(paste("NULL for ", varname))
# }
# if (!all(stan_data[[varname]] == stan_data2[[varname]])) {
# print(paste("mismatch ", varname))
# }
# }
The Stan model is located at src/models/deaths_and_111_calls.stan
:
stan_file <- "src/models/deaths_and_111_calls.stan"
lines <- readLines(stan_file)
cat(paste(lines, "\n", sep=""), sep="")
functions {
real[] seeiittd(real time,
real[] state,
real[] params,
real[] real_data,
int[] integer_data) {
// Unpack integer data values
int T = integer_data[1];
int n_beta_pieces = integer_data[2];
int n_disease_states = integer_data[3];
// Unpack real data values
real beta_left_t[n_beta_pieces] = real_data[1:n_beta_pieces];
real beta_right_t[n_beta_pieces] = real_data[n_beta_pieces+1:2*n_beta_pieces];
real population = real_data[2*n_beta_pieces+1];
// Unpack parameter values
real beta_left[n_beta_pieces] = params[1:n_beta_pieces];
real grad_beta[n_beta_pieces] = params[n_beta_pieces+1:2*n_beta_pieces];
real nu = params[2*n_beta_pieces+1];
real gamma = params[2*n_beta_pieces+2];
real kappa = params[2*n_beta_pieces+3];
real omega = params[2*n_beta_pieces+4];
// Unpack state
real S = state[1];
real E1 = state[2];
real E2 = state[3];
real I1 = state[4];
real I2 = state[5];
real T1 = state[6];
real T2 = state[7];
real D = state[8];
real infection_rate;
real nuE1 = nu * E1;
real nuE2 = nu * E2;
real gammaI1 = gamma * I1;
real gammaI2 = gamma * I2;
real kappaT1 = kappa * T1;
real kappaT2 = kappa * T2;
real dS_dt;
real dE1_dt;
real dE2_dt;
real dI1_dt;
real dI2_dt;
real dT1_dt;
real dT2_dt;
real dD_dt;
for (i in 1:n_beta_pieces) {
if(time >= beta_left_t[i] && time < beta_right_t[i]) {
real beta = grad_beta[i] * (time - beta_left_t[i]) + beta_left[i];
infection_rate = beta * (I1 + I2) * S / population;
}
}
dS_dt = -infection_rate;
dE1_dt = infection_rate - nuE1;
dE2_dt = nuE1 - nuE2;
dI1_dt = nuE2 - gammaI1;
dI2_dt = gammaI1 - gammaI2;
dT1_dt = gammaI2 * omega - kappaT1;
dT2_dt = kappaT1 - kappaT2;
dD_dt = kappaT2;
return {dS_dt, dE1_dt, dE2_dt, dI1_dt, dI2_dt, dT1_dt, dT2_dt, dD_dt};
}
real[ , ] integrate_ode_explicit_trapezoidal(real[] initial_state, real initial_time, real[] times, real[] params, real[] real_data, int[] integer_data) {
real h;
vector[size(initial_state)] dstate_dt_initial_time;
vector[size(initial_state)] dstate_dt_tidx;
vector[size(initial_state)] k;
real state_estimate[size(times),size(initial_state)];
h = times[1] - initial_time;
dstate_dt_initial_time = to_vector(seeiittd(initial_time, initial_state, params, real_data, integer_data));
k = h*dstate_dt_initial_time;
state_estimate[1,] = to_array_1d(to_vector(initial_state) + h*(dstate_dt_initial_time + to_vector(seeiittd(times[1], to_array_1d(to_vector(initial_state)+k), params, real_data, integer_data)))/2);
for (tidx in 1:size(times)-1) {
h = (times[tidx+1] - times[tidx]);
dstate_dt_tidx = to_vector(seeiittd(times[tidx], state_estimate[tidx], params, real_data, integer_data));
k = h*dstate_dt_tidx;
state_estimate[tidx+1,] = to_array_1d(to_vector(state_estimate[tidx,]) + h*(dstate_dt_tidx + to_vector(seeiittd(times[tidx+1], to_array_1d(to_vector(state_estimate[tidx,])+k), params, real_data, integer_data)))/2);
}
return state_estimate;
}
}
data {
real initial_time;
int<lower=1> n_beta_pieces;
real<lower=0> beta_left_t[n_beta_pieces];
real<lower=0> beta_right_t[n_beta_pieces];
int<lower=1> n_rho_calls_111_pieces;
int<lower=0> rho_calls_111_left_t[n_rho_calls_111_pieces];
int<lower=0> rho_calls_111_right_t[n_rho_calls_111_pieces];
int<lower=1> T;
real times[T];
int<lower=1> n_disease_states;
real<lower=0> population;
int<lower=1> deaths_length;
int<lower=1> deaths_starts[deaths_length];
int<lower=1> deaths_stops[deaths_length];
int<lower=0> deaths[deaths_length];
int<lower=1> calls_111_length;
int<lower=1> calls_111_start;
int<lower=0> calls_111[calls_111_length];
int real_data_length;
real real_data[real_data_length];
int integer_data_length;
int integer_data[integer_data_length];
int<lower=0, upper=1> compute_likelihood;
}
transformed data {
real mu_dL = 4.00;
real sigma_dL = 0.20;
real mu_dI = 3.06;
real sigma_dI = 0.21;
real mu_dT = 16.00;
real sigma_dT = 0.71;
int max_lag = 13;
}
parameters {
real<lower=0, upper=1> initial_state_raw[2];
real<lower=0> beta_left[n_beta_pieces];
real<lower=0> beta_right[n_beta_pieces];
real<lower=0> dL;
real<lower=0> dI;
real<lower=0> dT;
real<lower=0, upper=1> omega;
real<lower=0> reciprocal_phi_deaths;
real<lower=0> reciprocal_phi_calls_111;
real<lower=0> rho_calls_111[n_rho_calls_111_pieces];
simplex[max_lag+1] lag_weights_calls_111;
}
transformed parameters {
real initial_state[n_disease_states];
real grad_beta[n_beta_pieces];
real nu;
real gamma;
real kappa;
real phi_deaths;
real phi_calls_111;
real state_estimate[T,n_disease_states];
vector[T+1] S;
vector[T+1] E1;
vector[T+1] E2;
vector[T+1] I1;
vector[T+1] I2;
vector[T+1] T1;
vector[T+1] T2;
vector[T+1] D;
vector[T] daily_infections;
vector[T] daily_deaths;
vector[T] calls_111_lagged_daily_infections;
vector[T] daily_calls_111;
initial_state[1] = (population-5.0)*initial_state_raw[1] + 1.0;
initial_state[2] = (population-5.0)*(1.0-initial_state_raw[1])*initial_state_raw[2]/2.0 + 1.0;
initial_state[3] = (population-5.0)*(1.0-initial_state_raw[1])*initial_state_raw[2]/2.0 + 1.0;
initial_state[4] = (population-5.0)*(1.0-initial_state_raw[1])*(1.0-initial_state_raw[2])/2.0 + 1.0;
initial_state[5] = (population-5.0)*(1.0-initial_state_raw[1])*(1.0-initial_state_raw[2])/2.0 + 1.0;
initial_state[6] = 0.0;
initial_state[7] = 0.0;
initial_state[8] = 0.0;
grad_beta = to_array_1d((to_vector(beta_right) - to_vector(beta_left))./(to_vector(beta_right_t) -
to_vector(beta_left_t)));
nu = 2.0/dL;
gamma = 2.0/dI;
kappa = 2.0/dT;
phi_deaths = 1.0 / reciprocal_phi_deaths;
phi_calls_111 = 1.0 / reciprocal_phi_calls_111;
{
real params[2*n_beta_pieces+4];
params[1:n_beta_pieces] = beta_left;
params[n_beta_pieces+1:2*n_beta_pieces] = grad_beta;
params[2*n_beta_pieces+1] = nu;
params[2*n_beta_pieces+2] = gamma;
params[2*n_beta_pieces+3] = kappa;
params[2*n_beta_pieces+4] = omega;
state_estimate = integrate_ode_explicit_trapezoidal(initial_state, initial_time, times, params, real_data, integer_data);
}
S = append_row(initial_state[1], to_vector(state_estimate[, 1]));
E1 = append_row(initial_state[2], to_vector(state_estimate[, 2]));
E2 = append_row(initial_state[3], to_vector(state_estimate[, 3]));
I1 = append_row(initial_state[4], to_vector(state_estimate[, 4]));
I2 = append_row(initial_state[5], to_vector(state_estimate[, 5]));
T1 = append_row(initial_state[6], to_vector(state_estimate[, 6]));
T2 = append_row(initial_state[7], to_vector(state_estimate[, 7]));
D = append_row(initial_state[8], to_vector(state_estimate[, 8]));
daily_infections = S[:T] - S[2:] + machine_precision();
daily_deaths = D[2:] - D[:T];
calls_111_lagged_daily_infections = lag_weights_calls_111[1]*daily_infections;
for (i in 1:max_lag) {
calls_111_lagged_daily_infections += lag_weights_calls_111[i+1]*
append_row(rep_vector(0.0, i), daily_infections[:T-i]);
}
daily_calls_111 = rep_vector(0.0, T);
for (i in 1:n_rho_calls_111_pieces) {
daily_calls_111[rho_calls_111_left_t[i]:rho_calls_111_right_t[i]-1] =
calls_111_lagged_daily_infections[rho_calls_111_left_t[i]:rho_calls_111_right_t[i]-1] *
rho_calls_111[i];
}
}
model {
initial_state_raw[1] ~ beta(5.0, 0.5);
initial_state_raw[2] ~ beta(1.1, 1.1);
beta_left ~ normal(0, 0.5);
beta_right ~ normal(0, 0.5);
dL ~ normal(mu_dL, sigma_dL);
dI ~ normal(mu_dI, sigma_dI);
dT ~ normal(mu_dT, sigma_dT);
omega ~ beta(100, 9803);
reciprocal_phi_deaths ~ exponential(5);
reciprocal_phi_calls_111 ~ exponential(5);
rho_calls_111 ~ normal(0, 0.5);
lag_weights_calls_111 ~ dirichlet(rep_vector(0.1, max_lag+1));
if (compute_likelihood == 1) {
for (i in 1:deaths_length) {
target += neg_binomial_2_lpmf(deaths[i] |
sum(daily_deaths[deaths_starts[i]:deaths_stops[i]]), phi_deaths);
}
target += neg_binomial_2_lpmf(calls_111 |
daily_calls_111[calls_111_start:(calls_111_start-1)+calls_111_length], phi_calls_111);
}
}
generated quantities {
vector[T-1] growth_rate = (log(daily_infections[2:]) - log(daily_infections[:T-1]))*100;
int pred_deaths[deaths_length];
int pred_calls_111[calls_111_length];
for (i in 1:deaths_length) {
pred_deaths[i] = neg_binomial_2_rng(sum(daily_deaths[deaths_starts[i]:deaths_stops[i]]),
phi_deaths);
}
for (i in 1:calls_111_length) {
pred_calls_111[i] = neg_binomial_2_rng(daily_calls_111[calls_111_start - 1 + i],
phi_calls_111);
}
}
First some inits are setup:
set.seed(0)
initf <- function() {
n_beta_pieces <- stan_data$n_beta_pieces
initial_state_raw = c(runif(1, min = 0.99999, max = 1.0), runif(1, min = 0.0, max = 1.0))
beta_left = exp(runif(n_beta_pieces, min = -2, max = 0.5))
beta_right = exp(runif(n_beta_pieces, min = -2, max = 0.5))
dL = runif(1, min = 3.5, max = 4.0)
dI = runif(1, min = 2.2, max = 2.6)
dT = runif(1, min = 11.0, max = 13.0)
omega = 1/(1 + exp(-runif(1, min = -5, max = -3)))
list(
initial_state_raw = initial_state_raw,
beta_left = beta_left,
beta_right = beta_right,
dL = dL,
dI = dI,
dT = dT,
omega = omega
)
}
The code is run as:
library(cmdstanr)
library(rstan)
library(xfun)
model <- cmdstan_model(file.path("src","models","deaths_and_111_calls.stan"))
num_warmup <- 1000
num_samples <- 1000
num_chains <- 4
fit_1 <-
xfun::cache_rds({model$sample(data=stan_data,
seed=999,
chains=num_chains,
init = initf,
num_warmup=num_warmup,
num_samples=num_samples,
output_dir="output")},
rerun=FALSE, file="fit1", dir="_cache/")
rs_fit_1 <- rstan::read_stan_csv(fit_1$output_files())
print(fit_1$time())
$total
[1] 2287.373
$chains
chain_id warmup sampling total
1 1 256.025 185.119 441.144
2 2 275.761 173.661 449.422
3 3 472.499 221.388 693.887
4 4 442.008 260.252 702.260
#running some warmup and just 100 draws with two chains.
Viewing a text based summary of the fit, this will be very long, it is commented out and not run:
# fit_1$cmdstan_summary()
Below are the diagnostics used to help validate the model.
There are standard diagnostics that look for errors in the posterior.
fit_1$cmdstan_diagnose()
The prior predictive check estimates the model parameters without the likelihood being used. The resulting draws are then used to predict new data via predictive application of the likelihood given the draws. Note that compute_likelihood = 0
prevents the likelihood being computed in the model fitting step.
stan_data_no_likelihood <- stan_data
stan_data_no_likelihood$compute_likelihood <- 0
fit_2 <- xfun::cache_rds({model$sample(data=stan_data_no_likelihood, seed=999,
chains=num_chains, init = initf,
num_warmup=num_warmup,
num_samples=num_samples,
output_dir="output")},
rerun=TRUE, file="fit2", dir="_cache/")
rs_fit_2 <- rstan::read_stan_csv(fit_2$output_files())
rs_ex_fit_2 <- rstan::extract(rs_fit_2)
random_draws <- sample(1:nrow(rs_ex_fit_2$pred_deaths), 10, replace=FALSE)
deaths_draws <- t(rs_ex_fit_2$pred_deaths[random_draws,])
deaths_draws.df <- data.frame(deaths_draws)
names(deaths_draws.df) <- random_draws
draw_names <- colnames(deaths_draws.df)
weeks <- 1:nrow(deaths_draws.df)
p_data2.df <- cbind(deaths,weeks,deaths_draws.df)
p_long_data <- gather(p_data2.df, draw, deaths_sim, draw_names)
p3 <- ggplot(data=p_long_data, aes(x=weeks)) +
geom_line(aes(y=deaths_sim, group=draw, color=draw), size=.5) +
geom_line(aes(y=deaths), color="black", size=.5)
p3
Above we see the posterior of the priors without seeing any data. Generally some justification for prior distributions is expected. The above are weakly informative in that they cover a broad range of plausible values.
call_draws <- t(rs_ex_fit_2$pred_calls_111[random_draws,]) #keep same draws
call_draws.df <- data.frame(call_draws)
names(call_draws.df) <- random_draws
days <- 1:nrow(call_draws.df)
p_data3.df <- cbind(calls_111,days,call_draws.df)
p_long_data3 <- gather(p_data3.df, draw, calls_sim, draw_names)
p4 <- ggplot(data=p_long_data3, aes(x=days)) +
geom_point(aes(y=calls_sim, group=draw, color=draw), size=.5) +
geom_line(aes(y=calls_111), color="black", size=.5)
p4
Parameter recovery establishes that for some small set of values the model reasons properly. We pick a draw from the above distributions, simulate data with it and then attempt to recover the parameters that we simulated with. We can look at the above graph and pick expected outliers or close to actual data. For this we pick 42 as a middle-of-the-road example.
library(bayesplot)
#Pick one arbitrary draw from the prior distribution
draw <- 42
stan_data_3 <- stan_data
stan_data_3$calls_111 <- rs_ex_fit_2$pred_calls_111[42,]
stan_data_3$deaths <- rs_ex_fit_2$pred_deaths[42,]
stan_data_3$compute_likelihood <- 1
fit_3 <- xfun::cache_rds({model$sample(data=stan_data_3, seed=999,
chains=num_chains, init = initf,
num_warmup=num_warmup,
num_samples=num_samples,
output_dir="output")},
rerun=TRUE, file="fit3", dir="_cache/")
rs_fit_3 <- rstan::read_stan_csv(fit_3$output_files())
rs_fit_3_draws <- rstan::extract(rs_fit_3)
mcmc_intervals(fit_3$draws(variables=c("dL", "dI", "dT","omega")))
A subset of the estimated paramters shown, mean, 50% and 90% intervals indicated. Actual values below:
report <- paste(sprintf("Draw number %d", draw),
sprintf("actual dL=%.2f", rs_ex_fit_2$dL[draw]),
sprintf("actual dI=%.2f", rs_ex_fit_2$dI[draw]),
sprintf("actual dT=%.2f", rs_ex_fit_2$dT[draw]),
sprintf("actual omega=%.2f", rs_ex_fit_2$omega[draw]),
sep="\n")
cat(report)
Draw number 42
actual dL=3.81
actual dI=3.36
actual dT=16.43
actual omega=0.01
Compare predicted data from original run that used actual data.
rs_fit_1_draws <- rstan::extract(rs_fit_1)
summary.df <- as.data.frame(summary(rs_fit_1,pars=c("pred_deaths"), probs=c(.05,.5,.95))$summary)
weeks <- 1:length(deaths)
all.df <- cbind(summary.df, deaths, weeks)
colnames(all.df) <- make.names(colnames(all.df)) # to remove % in the col names
p4 <- ggplot(all.df, mapping = aes(x = weeks)) +
geom_ribbon(aes(ymin = X5., ymax = X95.), fill = "orange", alpha = 0.6) +
geom_line(mapping = aes(y = X50.)) +
geom_point(mapping = aes(y = deaths)) +
labs(x = "Week", y = "Deaths")
p4
Actual deaths are black dots, mean predicted deaths black line, orange ribbon spans central 95% of draws.
rs_fit_1_draws <- rstan::extract(rs_fit_1)
summary_2.df <- as.data.frame(summary(rs_fit_1,pars=c("pred_calls_111"), probs=c(.05,.5,.95))$summary)
days <- 1:length(calls_111)
all_2.df <- cbind(summary_2.df, calls_111, days)
colnames(all_2.df) <- make.names(colnames(all_2.df)) # to remove % in the col names
p5 <- ggplot(all_2.df, mapping = aes(x = days)) +
geom_ribbon(aes(ymin = X5., ymax = X95.), fill = "green", alpha = 0.6) +
geom_line(mapping = aes(y = X50.)) +
geom_point(mapping = aes(y = calls_111)) +
labs(x = "Day", y = "Calls 111")
p5
Actual calls are black dots, mean predicted calls black line, green ribbon spans central 90% of draws.
Impact of param changes on predictions.
devtools::session_info()
Error in get(genname, envir = envir) : object 'testthat_print' not found
─ Session info ───────────────────────────────────────────────────────────────
setting value
version R version 3.6.2 (2019-12-12)
os macOS Catalina 10.15.7
system x86_64, darwin15.6.0
ui X11
language (EN)
collate en_US.UTF-8
ctype en_US.UTF-8
tz America/New_York
date 2021-03-26
─ Packages ───────────────────────────────────────────────────────────────────
package * version date lib source
abind 1.4-5 2016-07-21 [1] CRAN (R 3.6.0)
assertthat 0.2.1 2019-03-21 [1] CRAN (R 3.6.0)
backports 1.1.5 2019-10-02 [1] CRAN (R 3.6.0)
bayesplot * 1.7.1 2019-12-01 [1] CRAN (R 3.6.0)
callr 3.4.3 2020-03-28 [1] CRAN (R 3.6.2)
checkmate 1.9.4 2019-07-04 [1] CRAN (R 3.6.0)
cli 2.0.2 2020-02-28 [1] CRAN (R 3.6.0)
cmdstanr * 0.3.0 2021-02-24 [1] local
colorspace 1.4-1 2019-03-18 [1] CRAN (R 3.6.0)
crayon 1.3.4 2017-09-16 [1] CRAN (R 3.6.0)
data.table 1.12.8 2019-12-09 [1] CRAN (R 3.6.0)
desc 1.2.0 2018-05-01 [1] CRAN (R 3.6.0)
devtools 2.3.1 2020-07-21 [1] CRAN (R 3.6.2)
digest 0.6.23 2019-11-23 [1] CRAN (R 3.6.0)
DirichletReg * 0.7-0 2020-05-29 [1] CRAN (R 3.6.2)
dplyr 0.8.3 2019-07-04 [1] CRAN (R 3.6.0)
ellipsis 0.3.0 2019-09-20 [1] CRAN (R 3.6.0)
evaluate 0.14 2019-05-28 [1] CRAN (R 3.6.0)
fansi 0.4.0 2018-10-05 [1] CRAN (R 3.6.0)
farver 2.0.1 2019-11-13 [1] CRAN (R 3.6.0)
Formula * 1.2-3 2018-05-03 [1] CRAN (R 3.6.0)
fs 1.3.1 2019-05-06 [1] CRAN (R 3.6.0)
ggplot2 * 3.2.1 2019-08-10 [1] CRAN (R 3.6.0)
ggridges 0.5.2 2020-01-12 [1] CRAN (R 3.6.0)
glue 1.3.1 2019-03-12 [1] CRAN (R 3.6.0)
gridExtra * 2.3 2017-09-09 [1] CRAN (R 3.6.0)
gtable 0.3.0 2019-03-25 [1] CRAN (R 3.6.0)
htmltools 0.4.0 2019-10-04 [1] CRAN (R 3.6.0)
inline 0.3.15 2018-05-18 [1] CRAN (R 3.6.0)
jsonlite 1.7.0 2020-06-25 [1] CRAN (R 3.6.2)
knitr 1.28 2020-02-06 [1] CRAN (R 3.6.0)
labeling 0.3 2014-08-23 [1] CRAN (R 3.6.0)
lattice 0.20-38 2018-11-04 [1] CRAN (R 3.6.2)
lazyeval 0.2.2 2019-03-15 [1] CRAN (R 3.6.0)
lifecycle 0.2.0 2020-03-06 [1] CRAN (R 3.6.0)
loo 2.2.0 2019-12-19 [1] CRAN (R 3.6.0)
magrittr 1.5 2014-11-22 [1] CRAN (R 3.6.0)
matrixStats 0.55.0 2019-09-07 [1] CRAN (R 3.6.0)
maxLik 1.4-6 2020-11-24 [1] CRAN (R 3.6.2)
memoise 1.1.0 2017-04-21 [1] CRAN (R 3.6.0)
miscTools 0.6-26 2019-12-08 [1] CRAN (R 3.6.0)
munsell 0.5.0 2018-06-12 [1] CRAN (R 3.6.0)
pillar 1.4.3 2019-12-20 [1] CRAN (R 3.6.0)
pkgbuild 1.0.6 2019-10-09 [1] CRAN (R 3.6.0)
pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 3.6.0)
pkgload 1.0.2 2018-10-29 [1] CRAN (R 3.6.0)
plyr 1.8.5 2019-12-10 [1] CRAN (R 3.6.0)
posterior 0.1.3 2021-02-24 [1] local
prettyunits 1.0.2 2015-07-13 [1] CRAN (R 3.6.0)
processx 3.4.5 2020-11-30 [1] CRAN (R 3.6.2)
ps 1.3.0 2018-12-21 [1] CRAN (R 3.6.0)
purrr 0.3.3 2019-10-18 [1] CRAN (R 3.6.0)
R6 2.4.1 2019-11-12 [1] CRAN (R 3.6.0)
Rcpp 1.0.3 2019-11-08 [1] CRAN (R 3.6.0)
remotes 2.2.0 2020-07-21 [1] CRAN (R 3.6.2)
reshape2 1.4.3 2017-12-11 [1] CRAN (R 3.6.0)
rlang 0.4.10 2020-12-30 [1] CRAN (R 3.6.2)
rmarkdown 2.0 2019-12-12 [1] CRAN (R 3.6.0)
rprojroot 1.3-2 2018-01-03 [1] CRAN (R 3.6.0)
rstan * 2.19.3 2020-02-11 [1] CRAN (R 3.6.0)
sandwich 3.0-0 2020-10-02 [1] CRAN (R 3.6.2)
scales 1.1.0 2019-11-18 [1] CRAN (R 3.6.0)
sessioninfo 1.1.1 2018-11-05 [1] CRAN (R 3.6.0)
StanHeaders * 2.21.0-1 2020-01-19 [1] CRAN (R 3.6.0)
stringi 1.4.3 2019-03-12 [1] CRAN (R 3.6.0)
stringr 1.4.0 2019-02-10 [1] CRAN (R 3.6.0)
testthat 2.3.2 2020-03-02 [1] CRAN (R 3.6.0)
tibble 3.0.3 2020-07-10 [1] CRAN (R 3.6.2)
tidyr * 1.0.0 2019-09-11 [1] CRAN (R 3.6.0)
tidyselect 1.1.0 2020-05-11 [1] CRAN (R 3.6.2)
usethis 1.6.1 2020-04-29 [1] CRAN (R 3.6.2)
vctrs 0.3.1 2020-06-05 [1] CRAN (R 3.6.2)
withr 2.1.2 2018-03-15 [1] CRAN (R 3.6.0)
xfun * 0.22 2021-03-11 [1] CRAN (R 3.6.2)
yaml 2.2.0 2018-07-25 [1] CRAN (R 3.6.0)
zoo 1.8-7 2020-01-10 [1] CRAN (R 3.6.0)
[1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library