I am trying to specify a hurdle adjacent category shift model, but whenever specials = "ordinal" is supplied, brm will generate a block of unfinished function - as a custom family is not recognized in stan_ordinal_lpmf(). Are there any alternatives?
For example:
hurdle_acat <- custom_family(
"hurdle_acat",
dpars = c("mu", "hu", "disc"),
links = c("logit", "logit", "log"),
type = "int",
specials = "ordinal",
threshold = "flexible"
)
stan_funs <- "
// acat
real acat_logit_lpmf(int y, real mu, real disc, vector thres) {
int nthres = num_elements(thres);
vector[nthres + 1] p = append_row(0, cumulative_sum(disc * (mu - thres)));
return p[y] - log_sum_exp(p);
}
// hurdle acat
real hurdle_acat_logit_lpmf(int y, real mu, real hu, real disc, vector thres) {
if (y == 0) {
return bernoulli_lpmf(1 | hu);
} else {
return bernoulli_lpmf(0 | hu) +
acat_logit_lpmf(y | mu, disc, thres);
}
}
real hurdle_acat_logit_merged_lpmf(int y, real mu, real hu, real disc, vector thres, array[] int j) {
return hurdle_acat_logit_lpmf(y | mu, hu, disc, thres[j[1]:j[2]]);
}
"
stanvars <- stanvar(scode = stan_funs, block = "functions")
make_stancode(formula = formula, data = df, family = hurdle_acat, stanvars = stanvars)
It returns:
// generated with brms 2.23.0
functions {
/* custom-logit log-PDF for a single response
* Args:
* y: response category
* mu: latent mean parameter
* disc: discrimination parameter
* thres: ordinal thresholds
* Returns:
* a scalar to be added to the log posterior
*/
real custom_logit_lpmf(int y, real mu, real disc, vector thres) {
/* custom-logit log-PDF for a single response and merged thresholds
* Args:
* y: response category
* mu: latent mean parameter
* disc: discrimination parameter
* thres: vector of merged ordinal thresholds
* j: start and end index for the applid threshold within 'thres'
* Returns:
* a scalar to be added to the log posterior
*/
real custom_logit_merged_lpmf(int y, real mu, real disc, vector thres, array[] int j) {
return custom_logit_lpmf(y | mu, disc, thres[j[1]:j[2]]);
}
// acat
real acat_logit_lpmf(int y, real mu, real disc, vector thres) {
int nthres = num_elements(thres);
vector[nthres + 1] p = append_row(0, cumulative_sum(disc * (mu - thres)));
return p[y] - log_sum_exp(p);
}
// hurdle acat
real hurdle_acat_logit_lpmf(int y, real mu, real hu, real disc, vector thres) {
if (y == 0) {
return bernoulli_lpmf(1 | hu);
} else {
return bernoulli_lpmf(0 | hu) +
acat_logit_lpmf(y | mu, disc, thres);
}
}
real hurdle_acat_logit_merged_lpmf(int y, real mu, real hu, real disc, vector thres, array[] int j) {
return hurdle_acat_logit_lpmf(y | mu, hu, disc, thres[j[1]:j[2]]);
}
}