Population Surges and Falls

The yearly percentage changes in population for various countries from 1961 to 2023, highlighting significant increases and sharp declines.

#TidyTuesday
A4 Size Viz
World Bank
Author

Aditya Dahiya

Published

May 22, 2024

How I made this graphic?

Getting the data

Code
# Data Import and Wrangling Tools
library(tidyverse)            # All things tidy
library(janitor)              # Cleaning names etc.
library(wbstats)              # Fetching World Bank Data

# Final plot tools
library(scales)               # Nice Scales for ggplot2
library(fontawesome)          # Icons display in ggplot2
library(ggtext)               # Markdown text support for ggplot2
library(showtext)             # Display fonts in ggplot2
library(gganimate)            # For animation


rawdf <- wb_data(
  indicator = "SP.POP.TOTL",
  start_date = 1960,
  end_date = 2023,
  return_wide = FALSE,
  gapfill = TRUE,
  mrv = 65
)

Setting Parameters

Code
# Font for titles
font_add_google("Dosis",
  family = "title_font"
) 

# Font for the caption
font_add_google("Saira Extra Condensed",
  family = "caption_font"
) 

# Font for plot text
font_add_google("Saira Semi Condensed",
  family = "body_font"
) 

text_col <- "grey20"

text_hil <- "grey30"

mypal <- paletteer::paletteer_d("ggthemes::Hue_Circle")

showtext_auto()

bg_col <- "white"

# Caption stuff for the plot
sysfonts::font_add(
  family = "Font Awesome 6 Brands",
  regular = here::here("docs", "Font Awesome 6 Brands-Regular-400.otf")
)
github <- "&#xf09b"
github_username <- "aditya-dahiya"
xtwitter <- "&#xe61b"
xtwitter_username <- "@adityadahiyaias"
social_caption_1 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{github};</span> <span style='color: {text_col}'>{github_username}  </span>")
social_caption_2 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{xtwitter};</span> <span style='color: {text_col}'>{xtwitter_username}</span>")

ts = 80

plot_title <- "Global Population Trends: Surges and Declines (1961-2023)"

plot_subtitle <- glue::glue("The line charts highlight important demographic changes, with rapid population increases in the <b style='color:{mypal[16]}'>UAE</b> (1969-1977,<br>2007-2008) and <b style='color:{mypal[11]}'>Qatar</b> (2006-2008), likely due to immigration. In contrast, marked population declines are observed in<br>countries like <b style='color:{mypal[8]}'>Lebanon </b> (1978-79), <b style='color:{mypal[1]}'>Afghanistan </b> (1981-82), <b style='color:{mypal[7]}'>Kuwait  </b>(1990-91), <b style='color:{mypal[12]}'>Rwanda </b>(1994-95), <b style='color:{mypal[6]}'>Kosovo </b>(1998-1999),<br><b style='color:{mypal[14]}'>Syria</b> (2013-2014), <b style='color:{mypal[10]}'>Libya </b>(2012), and <b style='color:{mypal[15]}'>Ukraine </b>(2022), primarily resulting from wars. These patterns highlight the profound<br>impact of socio-political and environmental factors on population dynamics.")

str_view(plot_subtitle)

plot_caption <- paste0(
  "**Data:** World Bank Databank. |  ",
  "**Code:** ", 
  social_caption_1, 
  " |  **Graphics:** ", 
  social_caption_2
  )

inset_text <- "About the data: The data for these line charts is derived from the World Bank DataBank, specifically the dataset on total population (ID: SP.POP.TOTL). This dataset is based on the de facto definition of population, counting all residents regardless of legal status or citizenship, and provides midyear estimates. The primary sources include the United Nations Population Division's World Population Prospects (2022 Revision), census reports, statistical publications from national statistical offices, Eurostat's demographic statistics, the United Nations Statistical Division's Population and Vital Statistics Report, the U.S. Census Bureau's International Database, and the Secretariat of the Pacific Community's Statistics and Demography Programme. These comprehensive and reputable sources ensure the reliability and accuracy of the population data presented in the charts."

ggplot() +
  labs(subtitle = plot_subtitle) +
  theme(plot.subtitle = element_markdown())

Data Wrangling

Code
high_pop_countries <- rawdf |> 
  filter(date == 2022) |> 
  filter(value > 1e5) |> 
  pull(country)


df <- rawdf |> 
  select(
    country, year = date,
    value, iso2c
  ) |> 
  mutate(iso2c = str_to_lower(iso2c)) |>
  group_by(country) |> 
  mutate(increase = 100*(value - lead(value))/value) |> 
  mutate(disp_val = (increase > 13 | increase < -5)) |> 
  filter(country %in% high_pop_countries) |> 
  mutate(country = fct(country))

df |> 
  filter(disp_val) |> 
  distinct(country)

Visualization

Code
g_base <- df |> 
  ggplot(aes(x = year, 
             y = increase,
             group = country)) +
  geom_line(colour = "grey10", alpha = 0.2) +
  geom_point(
    data = df |> filter(disp_val),
    mapping = aes(colour = country),
    size = 3, 
    alpha = 0.5
  ) +
  ggrepel::geom_text_repel(
    data = df |> filter(disp_val),
    mapping = aes(
      label = paste0(country, "\n(", round(increase, 1), "%,", year, ")"),
      colour = country
    ),
    lineheight = 0.3,
    family = "body_font",
    size = ts / 4
  ) +
  geom_hline(yintercept = 0, colour = text_hil, linewidth = 1) +
  annotate(
    geom = "label",
    x = 1962,
    y = -8,
    hjust = 0, 
    vjust = 1,
    label = str_wrap(inset_text, 60),
    colour = text_hil,
    fill = bg_col,
    lineheight = 0.35,
    size = ts / 7,
    family = "caption_font",
    label.size = NA
  ) +
  annotate(
    geom = "label",
    x = 2010, 
    y = -25,
    label = "Name of the Country\n(% Population Change, Year)",
    family = "body_font",
    fontface = "bold",
    colour = mypal[1],
    lineheight = 0.3,
    size = ts / 3,
    fill = bg_col,
    hjust = 0.5,
    vjust = 0.5,
    label.padding = unit(0.15, "lines")
  ) +
  scale_x_continuous(
    expand = expansion(0), 
    breaks = seq(1960, 2020, 10),
    limits = c(1961, 2023)
  ) +
  scale_y_continuous(
    labels = label_number(suffix = "%")
  ) +
  scale_colour_manual(values = mypal) +
  labs(
    x = NULL, y = "Yearly population change (%)",
    title = plot_title,
    subtitle = plot_subtitle,
    caption = plot_caption
  ) +
  coord_cartesian(clip = "off") +
  theme_minimal(
    base_family = "body_font",
    base_size = ts
  ) +
  theme(
    legend.position = "none",
    axis.line.y = element_line(
      arrow = arrow(ends = "both", length = unit(10, "mm")),
      linewidth = 1,
      colour = text_hil
    ),
    panel.grid.major.y = element_line(
      colour = "grey90",
      linewidth = 0.5
    ),
    panel.grid.minor.y = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.grid.minor.x = element_blank(),
    plot.title = element_text(
      hjust = 0,
      family = "title_font",
      size = 2.5 * ts,
      colour = text_hil,
      margin = margin(10, 0, 3,0, "mm")
    ),
    plot.subtitle = element_markdown(
      lineheight = 0.35,
      hjust = 0,
      colour = text_col,
      margin = margin(0,0,5,0, "mm")
    ),
    plot.caption = element_textbox(
      hjust = 0.5,
      family = "caption_font",
      colour = text_hil
    ),
    plot.background = element_rect(
      fill = bg_col,
      colour = bg_col
    ),
    axis.title.y = element_text(margin = margin(0,0,0,5, "mm"), colour = text_col),
    axis.text.y = element_text(
      margin = margin(0,0,0,0, "mm"), 
      colour = text_col,
      size = 1.2 * ts),
    axis.text.x = element_text(
      margin = margin(0,0,0,0, "mm"), 
      colour = text_col,
      size = 1.1 * ts),
    axis.ticks.y = element_blank()
  ) 

# QR Code for the plot
url_graphics <- paste0(
  "https://aditya-dahiya.github.io/projects_presentations/projects/",
  # The file name of the current .qmd file
  "world_population_animated_donut",         
  ".html"
)
# remotes::install_github('coolbutuseless/ggqr')
# library(ggqr)
plot_qr <- ggplot(
  data = NULL, 
  aes(x = 0, y = 0, label = url_graphics)
  ) + 
  ggqr::geom_qr(
    colour = text_hil, 
    fill = bg_col,
    size = 1.9
    ) +
  coord_fixed() +
  theme_void() +
  theme(plot.background = element_rect(
    fill = NA, 
    colour = NA
    )
  )

library(patchwork)
g <- g_base +
  # Add QR Code to the plot
  inset_element(
    p = plot_qr, 
    left = 0.85, 
    right = 1,
    bottom = 0.75,
    top = 0.90, 
    align_to = "full",
    clip = FALSE
  ) +
  
  # Basix Plot Annotations
  plot_annotation(
    theme = theme(
      plot.background = element_rect(
        fill = bg_col, 
        colour = NA, 
        linewidth = 0
      )
    )
  )

Save graphic and a thumbnail

Code
ggsave(
  plot = g,
  filename = here::here("data_vizs", "a4_world_population_change.png"),
  height = 210 * 2,
  width = 297 * 2,
  units = "mm"
)

library(magick)
# Saving a thumbnail for the webpage
image_read(here::here("data_vizs", 
                      "a4_world_population_change.png")) |> 
  image_resize(geometry = "400") |> 
  image_write(here::here("data_vizs", "thumbnails", 
                         "world_population_change.png"))