I have a model with an outcome that is a truncated normal. I estimate Sigma for each level of a categorical variable. How do I compare the posterior SD for each group?
I cannot simply compare Sigma, as the SD will also depend on mu due to the truncation.
For comparing group means, posterior_epred()
solves the problem that the mean of a truncated normal is not equal to the mu parameter. Is there anything similar for the SD?
Below is a simple example, that should illustrate the problem.
library(brms)
a <- rnorm(1000, 1, 2)
b <- rnorm(1000, 6, 2)
df <- data.frame(gr = rep(c("a","b"), each = 1000),
value = c(a,b))
# Remove values below 0
df <- df[df$value > 0,]
sd(df$value[df$gr == "a"])
#> [1] 1.393734
sd(df$value[df$gr == "b"])
#> [1] 1.938442
m1 <- brm(bf(value | trunc(lb = 0) ~ 0+gr,
sigma ~ 0+gr),
data = df, silent = TRUE)
#> Compiling Stan program...
plot(m1)
The Sigma values above are log(Sigma).
To compare means, I can simply use conditional_effects()
, which use the posterior distribution of epreds by default, so this gives the correct posterior means for each group.
# Mean of posterior distributions
conditional_effects(m1)
To compare group SD, I could simulate several posterior predictions for each draw and calculate the SD for each group within each draw, but that seems excessive. Also, I’m unsure how many simulations I should make for each draw, to make the the uncertainty from the simulations negligible.
library(ggplot2)
library(tidybayes)
predicted_draws(m1, newdata = data.frame(gr = rep(c("a", "b"), each = 100))) |>
group_by(.draw, gr) |>
summarise(sd = sd(.prediction)) |>
ggplot(aes(gr, sd)) +
stat_eye()
#> `summarise()` has grouped output by '.draw'. You can override using the
#> `.groups` argument.
Created on 2022-04-28 by the reprex package (v2.0.0)