https://www.r-bloggers.com/2021/09/will-the-next-german-parliament-have-a-gigantic-size-a-law-and-coding-challenge-2/ R-bloggers R-bloggers R news and tutorials contributed by hundreds of R bloggers * Home * About * RSS * add your blog! * Learn R * R jobs + Submit a new job (it's free) + Browse latest jobs (also free) * Contact us Will the next German parliament have a gigantic size? A law and coding challenge... Posted on September 24, 2021 by Economics and R - R posts in R bloggers | 0 Comments [This article was first published on Economics and R - R posts, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here) --------------------------------------------------------------------- Want to share your content on R-bloggers? click here if you have a blog, or here if you don't. ShareTweet On Sunday (26th of September), we will have the main parliamentary elections in Germany. The deepl translation of the election law states: SS1 (1) Subject to the deviations resulting from this Act, the German Bundestag shall consist of 598 Members of Parliament. [...]" Well, the "deviations" led in the previous elections to a Bundestag with 703 members. And while in 2020 the law was reformed with the stated goal to have a smaller Bundestag, we may even end up this time with more than 800 members if current voting forecasts should indeed realize. This post first explains the problem, points out the challenges to implement the law in R, and then studies with R several scenarios, also to get an idea how variants of the election law would affect the size and composition of the Bundestag. The problem in a nutshell There are 299 electoral districts in Germany. For each district one direct candidate will be elected to the Bundestag. In addition to voting for their district representative, voters have a second vote for a party. Things would be easy if the second vote would just determine the remaining 299 of the 598 total seats that are not directly elected. But the core idea is instead that the 2nd votes determine parties' shares of all 598 seats. This means if a party would gain 50 seats according to the 2nd votes and also wins directly 40 electoral districts, it would just get 50-40=10 additional delegates beyond the direct candidates. But what if the party only would get 40 seats according to the 2nd votes and but wins 50 electoral districts? Then still all 50 direct candidates have to get a seat. According to the election law before 2011, the party would essentially get the 50-40=10 seats in addition: these additional seats are called Uberhangmandate. The largest number of Uberhangmandate occurred in the 2009 elections: 24, all for the CDU/CSU. That were roughly 10% of CDU/CSU's total seats. Besides distorting the proportions of seats resulting from 2nd votes such "Uberhangmandate" create other problems. In combination with the allocation of party seats across the 16 Bundeslander, the election system could lead to the paradoxical situation that an additional 2nd vote for a party in a Bundesland where it got Uberhangmandate would reduce the total number of seats of that party. That became apparent in the 2005 elections where due to the sudden death, elections in one district took place two weeks later and the CDU had incentives to get few 2nd votes (see e.g. Section 1 in Heese 2012). The constitutional court decided in 2012 that the election law must be designed such that the impact of Uberhangmandate is limited (roughly said there should not be more than 15 Uberhangmandate). Now how could you reform the law? Two main routes come quickly to mind: i) Reduce the number of electoral districts so that e.g. only 40% of the 598 seats are directly elected. While in theory still a large number of Uberhangmandate could occur, it would be considerably less likely. ii) If a party gets more direct seats than they would get according to their 2nd vote share, increase the size of the parliament until all parties' seats match their seats according to the 2nd vote share. In 2012 most parties (including the opposition) agreed to a reform of the election law that, mainly followed the 2nd approach: variably increase the size of the Bundestag. Was such a large consensus possible because no party really minded the outlook to get more member of parliament positions? While in 2013 we still had a moderate increase to only 631 seats in the Bundestag, in 2017 there were 709 seats. If current election forecasts should actually realize, the next Bundestag may even go substantially beyond 800 seats. The main reason is the low projection for 2nd votes for the CSU (the Bavarian version of the Christian democrats), which is still expected to win a huge number of direct seats. A rule of thumb forecast of parliament size Before getting into the intricacies of the election law, let us do some simple rule-of-thumb calculation. There is a great website www.mandatsrechner.de that collects forecasts and other relevant data to allow detailed predictions for the seat distribution. I copied the data based on the Forsa forecast from 09-21 for 2nd votes and Prognos Election.de from 09-17 for the direct seats. (You can find the csv file here.) We have separately for each Bundesland forecasts for each party that is expected to enter parliament: dat = read.csv("prognose_2021.csv",encoding="UTF-8") %>% select(-seats.mr) head(dat,8) ## land pop party votes direct ## 1 Schleswig-Holstein 2659792 CDU 389588 6 ## 2 Schleswig-Holstein 2659792 SPD 487012 5 ## 3 Schleswig-Holstein 2659792 Gruene 394052 0 ## 4 Schleswig-Holstein 2659792 Linke 80974 0 ## 5 Schleswig-Holstein 2659792 FDP 221930 0 ## 6 Schleswig-Holstein 2659792 AfD 122180 0 ## 7 Hamburg 1537766 CDU 177921 0 ## 8 Hamburg 1537766 SPD 280211 6 Let us compute for each party the share of 2nd votes and also its direct seats relative to a total number of 598 seats: total_votes = sum(dat$votes) dat %>% group_by(party) %>% summarize( votes = sum(votes), direct = sum(direct), share_votes = votes / total_votes, direct_over_598 = direct / 598 ) %>% arrange(share_votes) ## # A tibble: 7 x 5 ## party votes direct share_votes direct_over_598 ## ## 1 CSU 1917218 41 0.0448 0.0686 ## 2 Linke 2790931 5 0.0652 0.00836 ## 3 AfD 5116704 14 0.120 0.0234 ## 4 FDP 5116705 0 0.120 0 ## 5 Gruene 7907632 8 0.185 0.0134 ## 6 CDU 8316189 93 0.194 0.156 ## 7 SPD 11628872 138 0.272 0.231 We see that the CSU is projected to get only 4.48% of 2nd votes, yet its predicted 41 direct seats would be 6.86% of a parliament with 598 members. For all other parties the number of seats according to vote shares is larger than their number of direct seats. Roughly said, the key logic of the election law is that the parliament would be increased so that the 41 direct seats of the CSU correspond to the their 4.48% share of second votes. This rule of thumb calculation would yield a size of 598 * 6.86 / 4.48 = 915.7 That would be a gigantic, very crowded and expensive parliament. The details of the election law: A coding challenge The election law is of course much more complex than the rule of thumb calculation above because it has to deal with integer problems and allocation of seats not only between parties but also between the 16 Bundeslander. Furthermore, the fear of an excessively large parliament was stated as reason for another reform of the election law in 2020 by the governing parties. I thought it would be an interesting exercise to transform the relevant parts of current election law into R code that allows to compute the resulting size and seat distribution of the Bundestag given a data set as above as input. Well, I utterly failed... After an afternoon and evening of headaches I thought I had a correct interpretation of the law and implemented an algorithm. Yet, it turned out that my interpretation was wrong. I am deeply impressed by anybody who is able to implement the correct algorithm just by reading the law that describes the procedure! Thankfully, I then got the hint that there is an example calculation by the Bundeswahlleiter. That made the procedure indeed understandable. Also, after reading what is actually done, it even seems to be kind of consistent with what is written in the law... While for some people an understandable explanation may remove the fun of the coding challenge, there still remain some interesting steps. For example, implementing the Webster/Saint-Lague/Scheppers method described in SS6 (2) Sentences 2-7 with a minimum seat restriction. You can find my implementation here on Github. In the following section, I use the code to explore the size and composition of the parliament under the current law and under some variations. Some scenarios Baseline scenario Let us compute the 2021 seat distribution given the actual law with our forecast data: source("seat_calculator.R") res = compute.seats(dat) summarize.results(res) ## Total size: 841 seats ## # A tibble: 7 x 5 ## party vote_share seat_shares seats ueberhang ## ## 1 SPD 0.272 0.270 227 0 ## 2 CDU 0.194 0.194 163 0 ## 3 Gruene 0.185 0.184 155 0 ## 4 AfD 0.120 0.119 100 0 ## 5 FDP 0.120 0.119 100 0 ## 6 Linke 0.0652 0.0654 55 0 ## 7 CSU 0.0448 0.0488 41 3 We predict now a Bundestag that is still extremely large with 841 members. One reason why we don't reach the 915 members from our rule-of-thumb calculation is that the 2020 reform allows a total of 3 Uberhangmandate. In our scenario they would all go to the CSU, which thus would achieve 4.88% of seats while it only has 4.48% of votes. What if the CSU earns one less direct seat? Let's assume the SPD earns captures one more direct seat from the CSU. How large will the parliament then be? library(dplyrExtras) dat.mod = dat %>% mutate_rows(party=="CSU" & land=="Bayern", direct = direct-1) %>% mutate_rows(party=="SPD" & land=="Bayern", direct = direct+1) res = compute.seats(dat.mod) sum(res$seats) ## [1] 817 That would lead to a substantial reduction of 24 total seats from 841 to 817. For me it feels not like a well designed election system if a single electoral district can have such huge impact on the size of the parliament... Variant: Allowing 15 Uberhangmandate What would happen if the 2020 reform would have fully exhausted the limit of 15 Uberhangmandate the constitutional court seem to have imposed as maximum cap in its 2012 decision? We can compute it: res = compute.seats(dat,max.ueberhang = 15) summarize.results(res) ## Total size: 612 seats ## # A tibble: 7 x 5 ## party vote_share seat_shares seats ueberhang ## ## 1 SPD 0.272 0.265 162 0 ## 2 CDU 0.194 0.190 116 0 ## 3 Gruene 0.185 0.180 110 0 ## 4 AfD 0.120 0.118 72 0 ## 5 FDP 0.120 0.118 72 0 ## 6 CSU 0.0448 0.0670 41 14 ## 7 Linke 0.0652 0.0637 39 0 We now would get a nicely small Bundestag with only 612 seats, where the 14 seats above 598 are all Uberhangmandate for the CSU. Hard to imagine that such a law would be survive long after such an outcome, but at least we would have a nicely workable small Bundestag. Variant: Treating CDU and CSU as one party Another aspect of the 2020 reform is that Uberhangmandate in some Bundeslander are offset by a seat reduction of the party in other Bundeslander. For the CSU that has no effect, since it only can be elected in Bavaria. But what would happen if the CDU and CSU were treated as a single party in the algorithm? dat.mod = mutate_rows(dat, party=="CSU" & land=="Bayern", party="CDU") res = compute.seats(dat.mod,max.ueberhang = 3) res = mutate_rows(res, party=="CDU" & land=="Bayern", party="CSU") summarize.results(res) %>% select(-ueberhang) ## Total size: 632 seats ## # A tibble: 7 x 4 ## party vote_share seat_shares seats ## ## 1 SPD 0.272 0.271 171 ## 2 Gruene 0.185 0.184 116 ## 3 CDU 0.194 0.179 113 ## 4 AfD 0.120 0.119 75 ## 5 FDP 0.120 0.119 75 ## 6 CSU 0.0448 0.0649 41 ## 7 Linke 0.0652 0.0649 41 For the representation of results, we again distinguish between CDU and CSU. We now also find a relatively small parliament with only 632 seats. The CSU gets 6.49% of seats with only 4.48% of 2nd votes but the additional seats now come at the cost of the CDU. For the other parties vote shares and seat shares are roughly aligned. So while this solution would lead to a small parliament, the substantial over-representation of Bavarian members of parliament might create strong tensions in the CDU/CSU sister-ship. Variant: Reduce number of electorial districts The election reform from 2020 also determined that starting in 2024 the number of electoral districts is reduced from 299 to 280. What if this change would already be implemented this election? One problem is that we don't have a forecast of how the 280 direct seats would be distributed. For a guess, I simply distribute the 280 districts using the Saint-Lague-Scheppers method treating the original direct mandates as votes. dat.mod = mutate(dat, direct = sls(direct, 280)) res = compute.seats(dat.mod,max.ueberhang = 3) summarize.results(res) %>% select(-ueberhang) ## Total size: 773 seats ## # A tibble: 7 x 4 ## party vote_share seat_shares seats ## ## 1 SPD 0.272 0.270 209 ## 2 CDU 0.194 0.194 150 ## 3 Gruene 0.185 0.184 142 ## 4 AfD 0.120 0.119 92 ## 5 FDP 0.120 0.119 92 ## 6 Linke 0.0652 0.0647 50 ## 7 CSU 0.0448 0.0492 38 As result, we only find a moderate reduction leading to 773 seats. What if we reduce the districts to approximately 40% of the 598 seats? That would be 239 electoral districts: dat.mod = mutate(dat, direct = sls(direct, 239)) res = compute.seats(dat.mod,max.ueberhang = 3) summarize.results(res) %>% select(-ueberhang) ## Total size: 640 seats ## # A tibble: 7 x 4 ## party vote_share seat_shares seats ## ## 1 SPD 0.272 0.270 173 ## 2 CDU 0.194 0.194 124 ## 3 Gruene 0.185 0.184 118 ## 4 AfD 0.120 0.119 76 ## 5 FDP 0.120 0.119 76 ## 6 Linke 0.0652 0.0641 41 ## 7 CSU 0.0448 0.05 32 Now we find a more workable Bundestag with 640 members. I guess if we end up with a Bundestag above 800 members such a more ambitious reduction of electoral districts is a likely outcome of future legislation. Variant: Going Half British What if we would use the second vote to just determine the distribution of the 299 seats that are not directly elected in an electoral district? Then the size of the parliament could always be fixed to 598 seats. Let's compute the resulting seat distribution given our forecasts: dat %>% group_by(party) %>% summarize( direct = sum(direct), votes = sum(votes) ) %>% mutate( seats2 = sls(votes, 299), seats = direct + seats2 ) %>% mutate( vote_share = votes / sum(votes), seat_shares = seats / sum(seats) ) %>% arrange(desc(seats)) ## # A tibble: 7 x 7 ## party direct votes seats2 seats vote_share seat_shares ## ## 1 SPD 138 11628872 81 219 0.272 0.366 ## 2 CDU 93 8316189 58 151 0.194 0.253 ## 3 Gruene 8 7907632 55 63 0.185 0.105 ## 4 CSU 41 1917218 13 54 0.0448 0.0903 ## 5 AfD 14 5116704 36 50 0.120 0.0836 ## 6 FDP 0 5116705 36 36 0.120 0.0602 ## 7 Linke 5 2790931 20 25 0.0652 0.0418 While the SPD, CDU and CSU would substantially gains seats, the other parties lose. Would such scheme be constitutional? The German constitution actually restricts the election law in Article 39 only as follows: Members of the German Bundestag shall be elected by an universal, direct, free, equal and secret election. They are representatives of the whole people, not bound by orders and instructions and subject only to their conscience. I guess these criteria in the first sentence are also satisfied by the British system where all members of parliament are personally elected as winners of an electoral district. As a layman it seems a bit strange to me that the constitutional court and other institutions seem to emphasize that the 2nd votes should to such a large extend determine the proportion of parties' seats. The constitution rather explicitly states that members of the Bundestag shall not be bound by any party orders, which seems consistent with a more prominent role of the first vote that directly elects a candidate. Yet, it seems very unlikely that this scheme will ever be implemented. Will the parliament indeed be so huge? Well, I guess many people believe that the CSU will get in the end some more 2nd votes than currently predicted by traditional forecasts. But we will see on Sunday... ** Related ShareTweet To leave a comment for the author, please follow the link and comment on their blog: Economics and R - R posts. --------------------------------------------------------------------- R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job. --------------------------------------------------------------------- Want to share your content on R-bloggers? click here if you have a blog, or here if you don't. - Previous post [ ] [Go] [Your e-mail here ] [Subscribe] [RBloggers_][RBloggers_] R bloggers Facebook page Most viewed posts (weekly) * Machine Learning : Workflow * PCA vs Autoencoders for Dimensionality Reduction * 5 Ways to Subset a Data Frame in R * How to write the first for loop in R * Date Formats in R * forester: An AutoML R package for Tree-based Models * {emayili} Rendering R Markdown Sponsors Recent Posts * Will the next German parliament have a gigantic size? A law and coding challenge... * EARL ONLINE 2021: HIGHLIGHTS * Data Science Conference Austria 2021 * Easy Rolling Means with MazamaRollUtils * Roll up, roll up the NHS-R Community Conference 2021 is coming to town * {emayili} Styling Figures * Curating for @WeAreRLadies on Twitter * Creating a data pipeline with Github Actions & the {googledrive} package for the Canadian Premier League soccer data initiative! * GxP Compliance in Pharma Made Easier: Good Documentation Practices with R Markdown and {officedown} * R Variables and Constants * How to Rotate Axis Labels in ggplot2? * How to Rotate Axis Labels in ggplot2? * Learning Path: Shiny * R Print Output * The Most Dangerous Equation, or Why Small is Not Beautiful! RSS Jobs for R-users * Junior Data Scientist / Quantitative economist * Senior Quantitative Analyst * R programmer * Data Scientist - CGIAR Excellence in Agronomy (Ref No: DDG-R4D/DS /1/CG/EA/06/20) * Data Analytics Auditor, Future of Audit Lead @ London or Newcastle RSS python-bloggers.com (python/data-science news) * 3 Ways to Read Multiple CSV Files: For-Loop, Map, List Comprehension * Common mistakes we Data Scientists make * Netting income * PythonMusings #6: dplyr in Python? First impressions of the siuba (Xiao Ba ) module * Parallelisation of Model Evaluation and Hyperparameter Tuning in Sci Kit Learn * Parallelisation of Sci Kit Learning Python Models * Microsoft wants YOU to learn Python! (RMB Data Science Meetup) Full list of contributing R-bloggers Archives Archives [Select Month ] Other sites * SAS blogs * Jobs for R-users Copyright (c) 2021 | MH Corporate basic by MH Themes Never miss an update! Subscribe to R-bloggers to receive e-mails with the latest R posts. (You will not see this message again.) [ ] Submit Click here to close (This popup will not appear again)