Skip to content

Instantly share code, notes, and snippets.

@AlbertRapp
Created February 4, 2023 20:07
Show Gist options
  • Save AlbertRapp/2ac21c89f002095c0df292ff63088e7b to your computer and use it in GitHub Desktop.
Save AlbertRapp/2ac21c89f002095c0df292ff63088e7b to your computer and use it in GitHub Desktop.
democracy_index.qmd
```{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