Created
February 4, 2023 20:07
-
-
Save AlbertRapp/2ac21c89f002095c0df292ff63088e7b to your computer and use it in GitHub Desktop.
democracy_index.qmd
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
```{r} | |
setwd(here::here('democracy_index')) | |
library(tidyverse) | |
library(shadowtext) | |
library(ggiraph) | |
library(ggtext) | |
library(gdtools) | |
register_gfont("Roboto Mono") | |
addGFontHtmlDependency(family = "Roboto Mono") | |
register_gfont("Open Sans") | |
addGFontHtmlDependency(family = "Open Sans") | |
``` | |
Load Data | |
```{r} | |
# https://github.com/xmarquez/democracyData | |
scores <- democracyData::eiu |> | |
select(eiu_name = eiu_country, score = eiu, year, full_name = extended_country_name) | |
``` | |
```{r} | |
# Latest scores extracted manually from | |
# https://www.eiu.com/n/campaigns/democracy-index-2022/ | |
scores_2022 <- tibble( | |
input = read_lines('manual_2022.txt'), | |
score = parse_number(input), # grabs first number which luckily is the score, | |
country = str_extract(input, '[a-zA-Zô’ ]+') # Extra characters for Côte d’Ivoire | |
) |> | |
mutate(country = str_sub(country, end = -2)) |> | |
select(country, score) | |
``` | |
Correct some parsing and naming issues | |
```{r} | |
## Correcting the following parsing errors | |
# Warning: 2 parsing failures. | |
# row col expected actual | |
# 44 -- a number Timor-Leste 7.06 44 -1 9.58 5.93 5.56 6.88 7.35 | |
# 141 -- a number Guinea-Bissau 2.56 140= -2 4.00 0.00 3.33 3.13 2.35 | |
scores_2022[44, ] <- tibble(country = 'Timor Leste', score = 7.06) # Spelled without dash in other data | |
scores_2022[141, ] <- tibble(country = 'Guinea-Bissau', score = 2.56) | |
scores_2022 <- scores_2022 |> | |
mutate(country = if_else(country == 'Eswatini', 'eSwatini', country)) | |
``` | |
Next, fix more naming issues in order to merge the two data sets. | |
```{r} | |
non_compliant_eiu_names <- scores_2022 |> | |
filter(!(country %in% scores$eiu_name)) |> | |
pull(country) | |
replace_dict <- scores |> | |
filter(full_name %in% non_compliant_eiu_names, year == 2006) |> | |
select(eiu_name, non_compliant_name = full_name) | |
replacement_vector <- replace_dict$eiu_name | |
names(replacement_vector) <- paste0("^", replace_dict$non_compliant_name, "$") | |
str_replace_all(scores_2022$country, replacement_vector) | |
scores_2022_adjusted <- scores_2022 |> | |
mutate(eiu_name = str_replace_all(country, replacement_vector)) |> | |
mutate(year = 2022) | |
all_scores <- bind_rows(scores, scores_2022_adjusted) |> | |
arrange(eiu_name) |> | |
fill('full_name') |> | |
select(-country) |> | |
mutate( | |
full_name = case_when( | |
full_name == 'Russia (Soviet Union)' ~ 'Russia', | |
full_name == 'United States of America' ~ 'United States', | |
TRUE ~ full_name | |
) | |
) | |
``` | |
```{r} | |
selected_countries <- c('Norway', 'United States', 'India', 'Peru', 'Russia', 'China') | |
ranked_data <- all_scores |> | |
mutate( | |
democracy_status = case_when( | |
score >= 8 ~ 'Full democracy', | |
score >= 7 ~ 'Flawed democracy2', | |
score >= 6 ~ 'Flawed democracy1', | |
score >= 5 ~ 'Hybrid regime2', | |
score >= 4 ~ 'Hybrid regime1', | |
score >= 3 ~ 'Authoritarian regime3', | |
score >= 2 ~ 'Authoritarian regime2', | |
TRUE ~ 'Authoritarian regime1' | |
), | |
color = case_when( | |
democracy_status == 'Full democracy' ~ '#49558f', | |
democracy_status == 'Flawed democracy2'~ '#799ec2', | |
democracy_status == 'Flawed democracy1'~ '#afc5da', | |
democracy_status == 'Hybrid regime2'~ '#ffe4af', | |
democracy_status == 'Hybrid regime1'~ '#ffce6e', | |
democracy_status == 'Authoritarian regime3'~ '#ffa9a6', | |
democracy_status == 'Authoritarian regime2'~ '#f6423c', | |
TRUE ~ '#bf0f09', | |
), | |
text_color = if_else(color == '#49558f', '#E5E5E5', 'grey10'), | |
full_name = str_remove_all(full_name, "'") | |
) |> | |
group_by(year) |> | |
mutate(rank = row_number(desc(score))) | |
``` | |
Compute data for the border between democracy/regime groups | |
```{r} | |
border_data <- ranked_data |> | |
filter(!(year %in% c(2007, 2009)), !str_detect(democracy_status, 'Full')) |> | |
group_by(year, democracy_group = str_remove(democracy_status, '[1-3]')) |> | |
summarise(max_rank = max(167 - rank + 1), .groups = 'drop') | |
compute_step_border <- function(dem_group) { | |
border_data_dem_group <- border_data |> | |
filter(democracy_group == dem_group) | |
tibble( | |
democracy_group = dem_group, | |
x = c(rbind(border_data_dem_group$year - 0.5, border_data_dem_group$year + 0.5)), | |
y = rep(border_data_dem_group$max_rank, each = 2) + 0.5 | |
) | |
} | |
border_data_step <- map_dfr(unique(border_data$democracy_group), compute_step_border) | |
``` | |
Create plot | |
```{r} | |
y_pos_democracy_labels <- c(20, 75, 115, 160) | |
plt <- ranked_data |> | |
ggplot(aes(x = year, y = 167 - rank + 1)) + | |
geom_tile_interactive( | |
data = ranked_data, | |
aes(data_id = full_name, fill = color), height = 1 | |
) + | |
geom_step_interactive( | |
data = border_data_step, | |
aes(x = x, y = y, group = democracy_group, data_id = democracy_group), | |
linewidth = 1 | |
) + | |
geom_text_interactive( | |
data = ranked_data |> filter(!(full_name %in% selected_countries), year == 2022), | |
aes(data_id = full_name, label = paste0(rank, '. ', full_name)), | |
hjust = 0, | |
position = position_nudge(x = 0.55), | |
alpha = 0, | |
size = 5, | |
family = "Open Sans" | |
) + | |
geom_text_interactive( | |
data = ranked_data |> filter((full_name %in% selected_countries), year == 2022), | |
aes(data_id = full_name, label = paste0(rank, '. ', full_name) ), | |
hjust = 0, | |
position = position_nudge(x = 0.55), | |
alpha = 1, | |
size = 5, | |
family = "Open Sans" | |
) + | |
geom_text_interactive( | |
aes(data_id = full_name, label = score), | |
color = ranked_data$text_color, | |
alpha = 0, | |
size = 3.75, | |
hjust = 0.5, | |
position = position_nudge(y = -0.8), | |
family = "Open Sans", | |
fontface = 'bold' | |
) + | |
annotate( | |
'tile', | |
x = 2007, | |
y = 1:167, | |
fill = 'grey70', | |
height = 1.2, | |
width = 1.03, | |
col = 'grey70' | |
) + | |
annotate( | |
'tile', | |
x = 2009, | |
y = 1:167, | |
fill = 'grey70', | |
height = 1.2, | |
width = 1.03, | |
col = 'grey70' | |
) + | |
annotate( | |
'shadowtext', | |
x = 2006.5, | |
y = y_pos_democracy_labels, | |
label = c('Authoritarian regimes', 'Hybrid regimes', 'Flawed democracies', 'Full democracies'), | |
hjust = 0, | |
size = 6.5, | |
fontface = 'bold', | |
color = 'black', | |
bg.color = 'white', | |
family = "Open Sans" | |
) + | |
theme_minimal(base_size = 20, base_family = 'Open Sans') + | |
theme( | |
legend.position = 'none', | |
panel.grid = element_blank(), | |
plot.title = element_text( | |
family = 'Merriweather', | |
face = 'bold', | |
size = 32 | |
), | |
plot.subtitle = element_markdown(lineheight = 1.25), | |
plot.caption = element_markdown(family = 'Roboto Mono', size = 14) | |
) + | |
coord_cartesian(xlim = c(2005.5, 2027), ylim = c(1, 168.5), expand = FALSE) + | |
labs(x = element_blank(), y = element_blank()) + | |
scale_x_continuous( | |
breaks = 2006:2022, | |
labels = c('2006', paste0(0, 7:9), 10:22) | |
) + | |
labs( | |
title = 'The world’s most, and least, democratic countries in 2022', | |
subtitle = 'The Economist Intelligence Unit released their most recent global democracy index<br> <span style= "font-size:16pt;">**10=most democratic**</span>', | |
caption = 'Data: EIU | Design: The Economist Graphic Detail | Remake: Albert Rapp (Twitter: @rappa753)' | |
) + | |
scale_y_continuous(breaks = NULL) + | |
scale_fill_identity() | |
girafe( | |
ggobj = plt, | |
options = list( | |
opts_hover( | |
css = girafe_css( | |
css = 'user-select: none;', | |
area = 'height:12px;stroke:black;stroke-width:1px;opacity:1;', | |
text = 'fill-opacity:1;' | |
) | |
), | |
opts_hover_inv(css = girafe_css( | |
css = 'user-select: none; opacity:0.3;', | |
area = 'height:3px;', | |
)), | |
opts_sizing(rescale = FALSE) | |
), | |
height_svg = 12, | |
width_svg = 16 | |
) | |
``` | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment