% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/post_helpers.R
\name{posterior_to_prior}
\alias{posterior_to_prior}
\title{Extract Informative Priors from a Fitted Bayesian IRT Model}
\usage{
posterior_to_prior(
  model,
  item_var = item,
  person_var = id,
  mult = 1,
  target_link = c("source", "logit", "probit")
)
}
\arguments{
\item{model}{A fitted \code{\link[brms]{brmsfit}} object. Supported
parameterisations:
\describe{
\item{Polytomous ordinal}{e.g., \code{family = acat} with
\code{thres(gr = item)}, producing item-specific thresholds.}
\item{Dichotomous Rasch (random items)}{e.g.,
\code{response ~ 1 + (1 | item) + (1 | id)} with
\code{family = bernoulli()}.}
\item{Dichotomous 1PL (fixed items)}{e.g.,
\code{response ~ 0 + item + (1 | id)} with
\code{family = bernoulli()}.}
}}

\item{item_var}{An unquoted variable name identifying the item
grouping variable in the model data. Default is \code{item}.}

\item{person_var}{An unquoted variable name identifying the person
grouping variable in the model data. Default is \code{id}.}

\item{mult}{Numeric multiplier applied to each posterior SD before
it is used as the prior SD. Values > 1 widen the priors
(less informative); values < 1 tighten them. Default is 1
(use posterior SD directly).}

\item{target_link}{Character string specifying the link function of
the model the priors will be used with. One of \code{"logit"},
\code{"probit"}, or \code{"source"} (the default). When
\code{"source"}, the link function of the fitted model is used
and no transformation is applied. When different from the source
model's link, all location and scale parameters are rescaled
using the approximation \eqn{\beta_{\text{probit}} \approx
  \beta_{\text{logit}} / 1.7}. This is useful when transferring
priors from a logit-fitted model to a probit model or vice versa.}
}
\value{
A \code{\link[brms]{brmsprior}} object that can be supplied
to the \code{prior} argument of \code{\link[brms]{brm}} or
\code{\link[stats]{update}}.
}
\description{
Takes a fitted \code{\link[brms]{brmsfit}} object and constructs a
\code{\link[brms]{brmsprior}} object in which each item parameter
receives a \code{normal(mean, sd)} prior derived from its posterior
distribution. The person-level random effect SD prior is also
updated. The returned prior can be passed directly to
\code{\link[stats]{update}} (or \code{\link[brms]{brm}}) to refit
the model with empirical Bayes / informative priors — useful for
anchoring scales, warm-starting a model on new data, or
regularising estimation with small samples.
}
\details{
The function extracts all posterior draws via
\code{\link[brms]{as_draws_df}}, computes the mean and SD of each
parameter's marginal posterior, and constructs
\code{normal(mean, sd * mult)} priors.

\strong{Polytomous ordinal models} with grouped thresholds
(\code{thres(gr = item)}): each threshold receives its own prior
via \code{brms::set_prior("normal(...)", class = "Intercept",
group = item, coef = threshold_index)}.

\strong{Dichotomous Rasch models} parameterised as
\code{response ~ 1 + (1 | item) + (1 | id)}: priors are set on
the global intercept (\code{class = "Intercept"}), the item-level
SD (\code{class = "sd", group = item_var}), and the person-level
SD.

\strong{Dichotomous 1PL models} parameterised as
\code{response ~ 0 + item + (1 | id)}: each item-specific fixed
effect (e.g., \code{b_itemI1}) receives its own
\code{normal(mean, sd)} prior via
\code{brms::set_prior(..., class = "b", coef = "itemI1")}.

In all cases the person-level SD receives a
\code{normal(mean, sd * mult)} prior (brms applies the lower
bound of zero automatically for SD parameters).

\strong{Link function transformation:} When \code{target_link}
differs from the source model's link function, all parameters
(means and SDs) are rescaled by a factor of approximately 1.7.
This uses the well-known approximation that
\eqn{\Phi(x) \approx \text{logistic}(1.7 \, x)}, so
logit-scale parameters can be converted to probit-scale by
dividing by 1.7, and vice versa. The approximation is excellent
for parameters in the range \eqn{|\beta| < 3} and adequate
beyond that range.
}
\examples{
\donttest{
library(brms)
library(dplyr)
library(tidyr)
library(tibble)

# --- Partial Credit Model ---

df_pcm <- eRm::pcmdat2 \%>\%
  mutate(across(everything(), ~ .x + 1)) \%>\%
  rownames_to_column("id") \%>\%
  pivot_longer(!id, names_to = "item", values_to = "response")

fit_pcm <- brm(
  response | thres(gr = item) ~ 1 + (1 | id),
  data   = df_pcm,
  family = acat,
  chains = 4, cores = 2, iter = 1000 # use more iter (and cores if you have)
)

# Extract posterior-informed priors (same link)
new_priors <- posterior_to_prior(fit_pcm)
new_priors

# Narrow the prior's sd by a factor of 0.5
wide_priors <- posterior_to_prior(fit_pcm, mult = 0.5)

# Extract priors for use with a probit model
probit_priors <- posterior_to_prior(fit_pcm, target_link = "probit")

# --- Dichotomous 1PL (fixed item effects) ---

df_rm <- eRm::raschdat3 \%>\%
  as.data.frame() \%>\%
  rownames_to_column("id") \%>\%
  pivot_longer(!id, names_to = "item", values_to = "response")

fit_1pl <- brm(
  response ~ 0 + item + (1 | id),
  data   = df_rm,
  family = bernoulli(),
  chains = 4, cores = 2, iter = 1000 # use more iter (and cores if you have)
)

priors_1pl <- posterior_to_prior(fit_1pl)
priors_1pl

# Transfer logit priors to a probit refit
priors_probit <- posterior_to_prior(fit_1pl, target_link = "probit")
}

}
