-
Notifications
You must be signed in to change notification settings - Fork 309
Election Results
submitted by holnburger
With ggplot2 and gganimate we're able to animate the outcome of the German federal elections since 1957 by gender. We also want to illustrate our plot as close as possible to design of the German Tagesschau. Our goal is to have an appealing visualization of the differences between the electoral choices of men and women.
Unfortunately the data provided by the Bundeswahlleiter (electoral management body) is a bit messy, therefore we have to clean it first and translate it into a tidy data set. We use the package dplyr and tidyr for that. Of course I'd love to include the electoral choices of voters with a non-binary gender – unfortunately the Bundeswahlleiter doesn't include such data.
library(dplyr)
library(tidyr)
btw_data <- read.csv2(
"https://www.bundeswahlleiter.de/dam/jcr/f0610db5-f84c-430e-96e1-19be7f599e60/btw17_rws_zwst-1953.csv",
skip = 10
) %>%
select(-Altersgruppe.etwa.von.....bis.....Jahren) %>%
filter(Geschlecht != "Summe") %>%
gather(CDU, SPD, PDS.DIE.LINKE, GRÜNE, CSU, FDP, AfD, Sonstige, key = Partei, value = Wahlergebnis) %>%
mutate(Partei = ifelse(Partei == "PDS.DIE.LINKE", "Die Linke", Partei)) %>%
mutate(Partei = ifelse(Partei == "GRÜNE", "Die Grünen", Partei)) %>%
mutate(Partei = factor(Partei, levels = c("CDU", "SPD", "FDP", "CSU", "Die Grünen", "Die Linke", "AfD", "Sonstige"))) %>%
mutate(Geschlecht = ifelse(Geschlecht == "m", "männlich", "weiblich")) %>%
mutate(Wahlergebnis = Wahlergebnis / 100) %>%
replace_na(replace = list(Wahlergebnis = 0))
Because we also want fitting colors for the parties we'll define them in a vector which we use later for the visualization.
party_color <- c(
"AfD" = "#1a9fde",
"SPD" = "#e10b1f",
"CDU" = "#565656",
"CSU" = "#727272",
"Die Grünen" = "#499533",
"Die Linke" = "#bc3475",
"FDP" = "#e5d82d",
"Sonstige" = "#D3D3D3"
)
library(ggplot2)
library(gganimate)
btw_animated <- ggplot(btw_data, aes(x = Partei, y = Wahlergebnis, fill = Partei)) +
geom_hline(yintercept = 0.05, colour = "#D3D3D3", linetype = "dashed") +
geom_bar(position = "dodge", stat = "identity") +
geom_text(aes(label = scales::percent(Wahlergebnis),
y = Wahlergebnis + 0.01),
position = position_dodge(width = 0.9),
vjust = -0.5, size = 6, color = "black") +
labs(title = "Wahlergebnisse der Bundestagswahl {closest_state}",
subtitle = "Ergebnisse nach Geschlecht der WählerInnen*",
caption = "* 1994 und 1998 wurde die repräsentative Wahlstatistik durch den Gesetzgeber ausgesetzt",
x = "", y = "") +
theme_light(base_size = 16) +
guides(fill = FALSE) +
facet_grid(Geschlecht ~ .) +
scale_y_continuous(labels = scales::percent, limits = c(0, 0.59)) +
scale_fill_manual(values = party_color) +
transition_states(Bundestagswahl, 1, 3, wrap = FALSE) +
ease_aes('quadratic-in-out')
In this example we use transition_states()
with the arguments transition_length = 1
and state_length = 3
to give us enough time to read the outcomes between the transition through the years. We use the argument wrap = FALSE
because we don't want to have a smooth transition between the outcome of the last election and the first. With the easing set to ease_aes('quadratic-in-out')
we generate a dynamic and smooth transition between the different states.
Install gganimate using devtools::install_github('thomasp85/gganimate')
The Grammar
Misc
Examples