Skip to content

DavidBustamanteL/-InferenceOrderings

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

137 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Inference Orderings DMCP

Replication File: Dirichlet Monte Carlo Perturbations
Authors: Salvatore Barbaro and David Bustamante Lazo
(2026, manuscript submitted for publication)

Overview 📂

This README focuses exclusively on the main function and its internal subfunctions. Detailed descriptions of the code's functionality are included as comments within the provided main R-file.

This repository implements the function run_one_election() to estimate Condorcet cycle probabilities in ranked-choice elections using Dirichlet Monte Carlo perturbations of empirically observed preference distributions.

The function evaluates all 3-candidate subsets (triplets) in an election and computes the probability of observing a majority cycle under sampling uncertainty.

Data Accessibility 📊

We used the same CSES project data as provided in the replication files in Barbaro and Kurella (2025).

Script and Dataset List 🗂️

  1. Main Replication R-File:
    • All_Elections.R
  2. Datasets:
    • CSES project data: rankings.RData
    • Political Behaviour Weights (PBW): resW.RData

Controlled Randomness ⚙️

All replications use a fixed seed value for reproducibility:
Seed Value: 55234 (the main authors' zip code).

Computational Requirements 🖥️

  1. Linux operating system
  2. R version: 4.5.2 "[Not] Part in a Rumble"
  3. Required R Libraries:
    • dplyr
    • magrittr
    • tidyverse
    • tidyr
    • stringr
    • data.table
    • MCMCpack

WARNING ⚠️

The results have been tested WITH LINUX ONLY!

Urgent: If you run this script on Windows, you must adjust the function. In particular, do NOT use mclapply.

Alternatives:

  1. Run the (outcommented) Timing1 function without parallelization (it will take longer).
  2. Instead of mclapply, recode, under your own responsability, the function using the future.apply library available in CRAN:

Main Function

run_one_election(df, N, phi, seed, pseudocount, ord_levels)

This function executes the complete Condorcet-cycle simulation pipeline for a single election.

Arguments

  • df: a data.frame containing respondent-level rankings (rows = individuals, columns = candidates)
  • N: number of Dirichlet draws per triplet
  • phi: precision scaling parameter for the Dirichlet distribution
  • seed: random seed for reproducibility
  • pseudocount: unused placeholder argument
  • ord_levels: vector of the 13 admissible ranking orderings for three candidates (including ties)

Returns

The function returns a list containing:

  • ranking_all: empirical ranking frequencies for each triplet
  • vec_list: 13-category count vectors for each triplet
  • prop_list: normalized proportions for each triplet
  • perturbations: Dirichlet draws for each triplet
  • outcomes_by_triplet: Condorcet outcomes for each draw
  • overall_table: aggregated outcome counts
  • cycle_rate_by_triplet: cycle probability per triplet
  • overall_cycle_rate: global cycle probability
  • baseline_outcome: Condorcet outcome computed from empirical proportions (no perturbation)

Internal Workflow

1. Triplet Construction

All triplets are generated by combining the candidate columns.

For an election with m candidates, the number of triplets equals choose(m, 3).

Within each triplet, candidates are relabeled locally as A, B, and C to standardize processing.

2. Ranking Encoding

Each respondent’s ranking over A, B, C is converted into one of 13 canonical ordering strings:

  • $A \sim B \sim C$
  • $A \sim B \succ C$
  • $A \sim C \succ B$
  • $A \succ B \sim C$
  • $A \succ B \succ C$
  • $A \succ C \succ B$
  • $B \sim C \succ A$
  • $B \succ A \sim C$
  • $B \succ A \succ C$
  • $B \succ C \succ A$
  • $C \succ A \sim B$
  • $C \succ A \succ B$
  • $C \succ B \succ A$

The encoding logic works as follows:

  • Candidates tied at the same rank are joined with $\sim$.
  • The preferences of a candidate over another one are joined with $\succ$.

For every respondent, the reported ranking is mapped to exactly one canonical ordering string.

3. Frequency Vector Construction (make_vec13)

For each triplet:

  1. Ordering strings are tabulated.
  2. A fixed-length vector of length 13 is created.
  3. The order of entries matches ord_levels exactly.

Missing ordering types receive zero counts.

Outputs:

  • vec_list: raw frequency counts
  • prop_list: normalized proportions (counts divided by total)

4. Dirichlet Perturbations

Observed counts (frequencies) are scaled by the precision parameter:

α = φ · c

For each triplet, N draws are generated from a Dirichlet distribution using these alpha parameters.

Each draw represents a plausible population preference distribution consistent with the observed data.

Column ordering is enforced to match ord_levels to ensure stable indexing.

5. Pairwise Preference Shares (pair_share and idx)

For each of the 13 ordering types, contributions to pairwise contests are precomputed:

  • $A$ vs $B$
  • $A$ vs $C$
  • $B$ vs $C$

Rules:

  • Strict preference contributes 1.
  • Strict loss contributes 0.
  • Tie contributes 0.5.

Index sets (idx) store which ordering columns imply wins, losses, or ties for each candidate pair.

These index sets allow fast vectorized computation of pairwise majority shares from each Dirichlet draw.

6. Condorcet Outcome Classification (condorcet_outcomes_matrix)

For every Dirichlet draw:

  1. Pairwise vote shares are computed using the index sets.
  2. Pairwise winners are determined.
  3. A final outcome is assigned:
    • "A", "B", "C" if a Condorcet winner exists
    • "Tie" if majority relations are unresolved
    • "Cycle" if a majority cycle occurs

This classification is performed independently for every triplet and every draw.

7. Aggregation

The function computes:

  • cycle_rate_by_triplet: fraction of draws producing cycles for each triplet
  • overall_cycle_rate: fraction of cycles across all triplets and all draws
  • overall_table: total counts of each outcome
  • baseline_outcome: Condorcet outcome derived directly from empirical proportions

Minimal Usage

A single election can be analyzed, e.g., by calling:

res = run_one_election(elections[[Switzerland_2011]])

This runs the full Dirichlet perturbation and Condorcet classification pipeline for the first election in the list.

The returned object res is a list containing all intermediate and final results.

Key outputs:

  • res$overall_cycle_rate
    The overall probability of observing a Condorcet cycle across all triplets and all Dirichlet draws.
  • res$cycle_rate_by_triplet
    A vector containing the cycle probability for each individual triplet.
  • res$overall_table
    A frequency table of all outcomes ("A", "B", "C", "Tie", "Cycle") aggregated across draws and triplets.
  • res$baseline_outcome
    The Condorcet outcome is computed directly from the empirical preference proportions (without Dirichlet perturbation).

About

Replication file to Dirichlet Monte Carlo Perturbations - Barbaro&BustamanteLazo

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages