R codes for replicating the chart:
# Clear R environment:
rm(list = ls())
# Load data:
library(tidyverse)
read_csv("http://infographics.economist.com/databank/Economist_pensions.csv") -> pensions_data
# Rename for all columns:
names(pensions_data) <- c("country", "pop_over65", "gov_spending")
# Remove mising:
%>% filter(!is.na(gov_spending)) -> pensions_data
pensions_data
# The Financial colors (https://www.r-bloggers.com/2018/06/the-financial-times-and-bbc-use-r-for-publication-graphics/):
<- "#262a33"
bgr_color
<- "#ff0055"
pink_color
<- "#0d64fc"
blue1_color
<- "#526171"
grey_color
<- "#9b9da1"
grey_text
<- c("Brazil", "Turkey", "Mexico", "Poland", "South Kore", "Italy",
some_countries "United States", "France", "OECD average", "Japan", "Greece")
# Extract OECD countries from web:
"https://en.wikipedia.org/wiki/OECD" %>%
::read_html() %>%
rvest::html_nodes(xpath = '//*[@id="mw-content-text"]/div[1]/div[3]') %>%
rvest::html_text() %>%
rveststr_split("\n", simplify = TRUE) %>%
as.vector() %>%
-1] -> oecd_countries
.[
# Averages for OECD countries:
%>%
pensions_data filter(country %in% oecd_countries) %>%
mutate(country = "OECD average") %>%
group_by(country) %>%
summarise(pop_over65 = mean(pop_over65),
gov_spending = mean(gov_spending)) -> data_oecd
# Joint the two data sets:
bind_rows(pensions_data, data_oecd) -> data_for_ploting
%>%
data_for_ploting mutate(text_face = case_when(country == "Brazil" ~ "bold",
== "OECD average" ~ "italic",
country TRUE ~ "plain")) -> data_for_ploting
%>% filter(country %in% some_countries) -> df1
data_for_ploting
%>% filter(!country %in% some_countries) -> df2
data_for_ploting
<- "Brazil's golden oldie blowout"
p_title
<- "Latest available"
p_subtitle
<- "Source: OECD; World Bank; PrevidĂȘncia Social | Graphic Designer: Nguyen Chi Dung"
p_caption
<- "Government spending\non pension benefits\n% of GDP"
left_text
library(ggrepel)
library(showtext) # Package for using extra fonts.
# Fira Sans Condensed
<- "Fira Sans Condensed"
my_font
# Load font for ploting:
font_add_google(name = my_font, family = my_font)
showtext_auto() # Automatically render text.
ggplot() +
geom_point(data = data_for_ploting, aes(pop_over65, gov_spending), color = "#90aac6", size = 5, alpha = 0.4) +
geom_point(data = data_for_ploting %>% filter(country == "Brazil"),
aes(pop_over65, gov_spending), shape = 21, size = 5, fill = blue1_color, color = "white", stroke = 1) +
geom_point(data = data_for_ploting %>% filter(country %in% c("France", "Italy", "Greece", "Japan")),
aes(pop_over65, gov_spending), shape = 21, size = 5, fill = pink_color, color = "white", stroke = 1) +
geom_point(data = data_for_ploting %>% filter(country %in% c("United States", "OECD average")),
aes(pop_over65, gov_spending), color = pink_color, size = 5, alpha = 0.8) +
geom_point(data = data_for_ploting %>% filter(country %in% c("Mexico", "Turkey")),
aes(pop_over65, gov_spending), color = blue1_color, size = 5, alpha = 0.8) +
theme(plot.background = element_rect(fill = bgr_color, color = NA)) +
theme(panel.background = element_rect(fill = bgr_color, color = NA)) +
theme(panel.grid.major = element_line(size = 0.8, color = "#3e4046")) +
theme(panel.grid.minor = element_blank()) +
geom_text_repel(data = df1 %>% filter(country == "France"),
aes(pop_over65, gov_spending, label = country), force = 0, direction = "y", seed = 12,
family = my_font, size = 4, color = "grey95", nudge_y = 1) +
geom_text_repel(data = df1 %>% filter(country == "Greece"),
aes(pop_over65, gov_spending, label = country), force = 1, direction = "x", seed = 12,
family = my_font, size = 4, color = "grey95", nudge_x = 1.4) +
geom_text_repel(data = df1 %>% filter(country == "Italy"),
aes(pop_over65, gov_spending, label = country), force = 1, direction = "y", seed = 12,
family = my_font, size = 4, color = "grey95", nudge_y = 1) +
geom_text_repel(data = df1 %>% filter(country == "Japan"),
aes(pop_over65, gov_spending, label = country), force = 1, direction = "y", seed = 12,
family = my_font, size = 4, color = "grey95", nudge_y = -0.8) +
geom_text_repel(data = df1 %>% filter(country == "United States"),
aes(pop_over65, gov_spending, label = country), force = 4, direction = "x", seed = 12,
family = my_font, size = 4, color = "grey95", nudge_x = -2.4) +
geom_text_repel(data = df1 %>% filter(country == "OECD average"),
aes(pop_over65, gov_spending, label = country), force = 1, direction = "x", seed = 12,
family = my_font, size = 4, color = "grey95", nudge_x = -2.5, fontface = "italic") +
geom_text_repel(data = df1 %>% filter(country == "Brazil"),
aes(pop_over65, gov_spending, label = country), force = 1, direction = "y", seed = 12,
family = my_font, size = 4, nudge_y = 1.1, fontface = "bold", color = "white") +
geom_text_repel(data = df1 %>% filter(country == "Turkey"),
aes(pop_over65, gov_spending, label = country), force = 1, direction = "y", seed = 12,
family = my_font, size = 4, color = "grey95", nudge_y = 0.9) +
geom_text_repel(data = df1 %>% filter(country == "Mexico"),
aes(pop_over65, gov_spending, label = country), force = 1, direction = "y", seed = 12,
family = my_font, size = 4, color = "grey95", nudge_y = 0.9) +
labs(subtitle = left_text, x = "Population aged 65 years and over, % of total") +
scale_x_continuous(limits = c(5, 30.5), breaks = seq(5, 30, 5), expand = c(0, 0)) +
scale_y_continuous(limits = c(0, 20), breaks = seq(0, 20, 5), expand = c(0, 0), position = "right") +
theme(axis.title.y.right = element_blank()) +
theme(panel.grid.minor = element_blank()) +
theme(plot.subtitle = element_text(hjust = 1.05, color = "grey95", family = my_font, size = 12, vjust = 4)) +
theme(axis.title.x = element_text(color = "grey95", family = my_font, size = 12)) +
theme(axis.text = element_text(color = "grey95", family = my_font, size = 14)) -> p
library(patchwork)
+
p plot_annotation(title = p_title, subtitle = p_subtitle, caption = p_caption) +
plot_annotation(theme = theme(plot.background = element_rect(fill = bgr_color))) +
plot_annotation(theme = theme(plot.title = element_text(family = my_font, size = 18, face = "bold", vjust = -1.5, color = "white"))) +
plot_annotation(theme = theme(plot.subtitle = element_text(family = my_font, size = 13, color = "grey95", vjust = -2))) +
plot_annotation(theme = theme(plot.caption = element_text(family = my_font, color = "grey60", size = 11, hjust = 0))) +
theme(plot.margin = unit(c(0.5, 0.5, 0.1, 0.7), "cm"))
# Make Financial Times icon:
library(grid)
grid.rect(x = 0.055, y = 1, width = 0.05*1.7, height = 0.008, just = c("left", "top"), gp = gpar(fill = "grey95", col = "grey95"))