Compute Bayesian Prior-Posterior and Information Gain Curves
Source:R/bayes_curves_functions.R
make_bayes_curves.RdComputes Bayesian updating curves showing how different lineup responses update beliefs about suspect guilt, following Wells, Yang, & Smalarz (2015).
Arguments
- data
A dataframe with the following columns:
target_present: Logical. TRUE if guilty suspect in lineup
identification: Character. "suspect", "filler", or "reject"
confidence: Numeric. Confidence rating (optional for response categories)
- response_categories
Character vector specifying how to categorize responses. Options:
"simple": Three categories (suspect, filler, reject)
"confidence": Combines identification with confidence bins
- confidence_bins
Numeric vector of bin edges if using confidence categories (e.g., c(0, 60, 80, 100)). Ignored if response_categories = "simple".
- prior_grid
Numeric vector of prior probabilities to evaluate (default: seq(0.01, 0.99, 0.01))
- lineup_size
Nominal lineup size, used when target-absent data have no designated innocent suspect.
- innocent_suspect
How innocent-suspect identifications in target-absent lineups are obtained.
"designated": the lineups had a designated innocent suspect, so target-absent"suspect"rows are counted directly, and zero such rows means a false-ID rate of zero."estimated": there was no designated innocent suspect, so the innocent-suspect count is estimated as filler IDs divided bylineup_size."auto"(the default) chooses"designated"when any target-absent row is a suspect ID or the data have a non-missingsuspect_poscolumn, and"estimated"otherwise, with a message.
Value
A list containing:
curves: Dataframe with prior, posterior, and information gain for each response
likelihoods: Dataframe with p(x|guilty) and p(x|innocent) for each response
response_counts: Count of each response type by target presence
n_guilty: Number of target-present lineups
n_innocent: Number of target-absent lineups
Details
This function treats lineup outcomes as evidence for Bayesian updating. For each response type x (e.g., high-confidence suspect ID, rejection, etc.), it computes:
Likelihoods from observed data: $$p(x|guilty) = \frac{count(x | target\_present)}{N_{guilty}}$$ $$p(x|innocent) = \frac{count(x | target\_absent)}{N_{innocent}}$$
For each prior probability p(guilty): $$p(x) = p(guilty) \cdot p(x|guilty) + (1-p(guilty)) \cdot p(x|innocent)$$ $$p(guilty|x) = \frac{p(guilty) \cdot p(x|guilty)}{p(x)}$$
Information gain: $$IG(x) = H(prior) - H(posterior)$$
where H(p) is binary entropy.
The information gain quantifies how much uncertainty is reduced by observing response x. It is negative when the response moves belief towards 0.5, as a suspect identification does at a low prior; that is a correct update that leaves more uncertainty, not misleading evidence.
References
Wells, G. L., Yang, Y., & Smalarz, L. (2015). Eyewitness identification: Bayesian information gain, base-rate effect-equivalency curves, and reasonable suspicion. Law and Human Behavior, 39(2), 99-122.
Examples
data(lineup_example)
bayes <- make_bayes_curves(lineup_example)
bayes$likelihoods
#> # A tibble: 3 × 5
#> response p_x_given_guilty p_x_given_innocent n_guilty n_innocent
#> <chr> <dbl> <dbl> <int> <dbl>
#> 1 filler 0.311 0.587 218 411
#> 2 reject 0.0957 0.287 67 201
#> 3 suspect 0.593 0.126 415 88