This document is part of the replication folder for the article ‘Capturing Rationalization Bias and Differential Item Functioning: A Unified Bayesian Scaling Approach’ in Political Analysis. It provides an overview of functions that may be convenient for future use of the BAM2 and ISR models.

Loading key functions

The most relevant functions are included in the file functions_general.R. Assuming the replication folder is your working directory, the functions can be loaded as follows:

source("scripts/functions_general.R")

Preparing data

The function prep.data turns the data into a list that can be fed to rstan’s stan or sampling functions. The prep.data function takes a vector of \(N\) centered self-placements, an \(N \times J\) matrix of centered stimuli-placements (where \(J\) is the number of stimuli), and a similar matrix of preferences. While Stan does not accept NAs, the function does, and you can use the option allow.miss to set how many missing values to permit for an individual to still be included in the analysis. By default, an observation is counted as missing when either the preference or stimuli placement is missing. Adding the option req.only.Y = TRUE will ignore missing values on preferences, and consider only stimuli placements, which may be suitable when fitting the BAM2 model. The prep.data function can be used as follows:

load("data/data_example.R") # Loading a subset of Estonian data (from EES 2009).
dat <- prep.data(self, ppos, prefs, allow.miss = 1)

Fitting the models

The functions inits.BAM and inits.2 can be used to generate starting values. Given the similarities between the BAM2 and ISR models, inits.2 should be used for both, while the original BAM model would use inits.BAM. Fitting the models, we can either separate compilation and sampling, using stan_model and sampling (as in the article), or use stan to do both:

require("rstan")
fit.ISR <- stan(file = "models/m_ISR.stan", init = inits.2, data = dat, chains = 3, cores = 3, verbose = FALSE)
fit.BAM2 <- stan(file = "models/m_BAM2.stan", init = inits.2, data = dat, chains = 3, cores = 3, verbose = FALSE)

Extracting estimates

The function get.estimates extracts estimates from a fitted model. Because the function rescales the original self-placements, it also requires the data as input. The function returns a list of estimates, including 95% credible intervals as well as posterior means and medians. It can be used as follows:

est.ISR <- get.estimates(fit.ISR, dat)
est.BAM2 <- get.estimates(fit.BAM2, dat)

To see the structure of the returned object for a given model, use e.g. str(est.ISR).

Illustration

Below is a simple plot of posterior median estimates from both models. We see that the models disagree on whether the voters are flipping the scale in some instances where the ISR model detects high rationalization.

require(ggplot2)
d <- data.frame(est.ISR$vpos[, 2], est.BAM2$vpos[, 2], est.ISR$gamma.CI[, 2])
colnames(d) <- c("Voter estimate, ISR", "Voter estimate, BAM2", "Rationalization")
ggplot(d, aes(x = `Voter estimate, ISR`, y = `Voter estimate, BAM2`, color = Rationalization)) + geom_point(alpha = .7)