library(knitr) opts_chunk$set( fig.align = "center", fig.width = 4, fig.height = 4, warning = FALSE, crop = TRUE)
library(tidyr) library(purrr) library(dplyr) library(coalitions)
In this vignette we demonstrate the basic workflow using the most recent Emnid survey.
This package calculates coalition probabilities in multi-party systems. To this end we provide some convenience functions, the most important of which are listed below:
scrape_wahlrecht
: A wrapper function that download the most current
survey results from https://www.wahlrecht.de/
collapse_parties
: Transforms information on percentages received by
individual parties in long format and stores them inside a nested tibble
(see tidyr::nest
)
draw_from_posterior
: Draws nsim
samples from the posterior distribution
(i.e. nsim
simulated election results based on provided survey)
get_seats
: Obtain seat distributions for each simulation (see also ?sls
)
have_majority
: Given a list of coalitions of interest, calculates if the
respective coalition would have enough seats for a majority
calculate_probs
: Given majority tables obtained from have_majority
, calculates the probabilities for the respective coalitions to have enough
seats for a majority
# one line per survey (party information in wide format) emnid <- scrape_wahlrecht() %>% slice(1:6) emnid %>% select(-start, -end)
After applying collapse_parties
we still have one row per survey,
but information on parties and percentage of votes they received is
stored in a long format in a separate column (see ?tidyr::nest
):
elong <- collapse_parties(emnid) head(elong) elong %>% slice(1) %>% select(survey) %>% unnest("survey")
Based on each survey we can now simulate nsim
elections by drawing from the
Dirichlet distribution
set.seed(1) # for reproducibility elong <- elong %>% mutate(draws = map(survey, draw_from_posterior, nsim=10, correction=0.005)) elong %>% select(date, survey, draws) # each row is one election simulation elong %>% slice(1) %>% select(draws) %>% unnest("draws")
Given the simulated elections, we can calculate the number of seats each
party obtained. To do so we need to have a function that knows how to
redistribute seats for the particular election. In Germany for example,
seats are distributed according to the system of Sainte-Lague-Scheppers, which
is implemented in ?sls
.
This makes this package easily extensible to other
multi-party systems, as you only need to provide a function that redistributes
seats based on percentages obtained by the various parties and provide that
function to the distrib.fun
argument of the get_seats
function:
elong <- elong %>% mutate(seats = map2(draws, survey, get_seats, distrib.fun=sls)) elong %>% select(date, survey, draws, seats) ## sim column indicates simulated elections (rows in draws column) elong %>% slice(1) %>% select(seats) %>% unnest("seats")
In the above example, given the latest survey, CDU/CSU would have r elong %>% slice(1) %>% select(seats) %>% unnest("seats") %>% filter(party == "cdu" & sim == 1) %>% pull(seats)
seats
in the first simulation, r elong %>% slice(1) %>% select(seats) %>% unnest("seats") %>% filter(party == "cdu" & sim == 2) %>% pull(seats)
seats in the second simulation, etc.
The next step is to define coalitions of interest, then calculate in what percentage of the simulations the coalition would obtain enough seats for a majority.
Below, each list element defines one coalition of interest (one party could potentially obtain absolute majority on their own):
coalitions <- list( c("cdu"), c("cdu", "fdp"), c("cdu", "greens"), c("cdu", "fdp", "greens"), c("spd"), c("spd", "left"), c("spd", "greens"), c("spd", "left", "greens"), c("cdu", "spd")) elong <- elong %>% mutate(majorities = map(seats, have_majority, coalitions = coalitions)) elong %>% select(date, draws, seats, majorities) # The majorities table for each date will have 1 row per simulation # and one column per coalition elong %>% slice(1) %>% select(majorities) %>% unnest("majorities")
The last step is to calculate the coalition probabilities (note that
by default we exclude "superior" coalitions, i.e. if "cdu/csu" have a majority
on their own, this simulation will not be counted to the simulation with
majority for "cdu/csu" and "fdp", see example in ?calculate_probs
):
elong <- elong %>% mutate( probabilities = map(majorities, calculate_probs, coalitions=coalitions)) elong %>% select(date, majorities, probabilities) # one row per coalition elong %>% slice(1) %>% select(probabilities) %>% unnest("probabilities")
There is a wrapper function that directly returns probabilities:
elong <- collapse_parties(emnid) elong %>% get_probabilities(., nsim=10) %>% unnest("probabilities")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.