Carbon Majors Emissions Data

Historical Carbon Emissions

#TidyTuesday
Donut Chart
Animation
Author

Aditya Dahiya

Published

May 21, 2024

The Carbon Majors Emissions Data provides a comprehensive database of historical emissions from some of the world’s largest producers of oil, gas, coal, and cement. This dataset, compiled by Carbon Majors and acknowledged by Data is Plural, includes data from as far back as 1854. It covers 122 entities, which comprise 75 investor-owned companies, 36 state-owned companies, and 11 nation states. Among these are 82 oil producers, 81 gas producers, 49 coal producers, and 6 cement producers. The data is used to quantify both direct operational emissions and emissions from the combustion of marketed products attributable to these entities. This extensive dataset captures over 1.42 trillion tonnes of CO2, representing 72% of global fossil fuel and cement emissions since the Industrial Revolution began in 1751. The available data is categorized with medium granularity, detailing information by year, entity, entity type, commodity, commodity production, commodity unit, and total emissions.

This animated donut chart illustrates the changing year-wise share of CO2 emissions from coal (6 different types of Coal), oil, and natural gas, highlighting key shifts in energy sources over time.

The analysis of the Carbon Majors Emissions Data reveals significant trends in the sources of CO2 emissions over time. Historically, coal has been the predominant source of CO2 emissions, maintaining this status for much of human history. However, starting in the late 1970s, the share of emissions from oil, natural gas liquids (NGL), and natural gas began to rise significantly. This shift indicates a diversification in energy sources and their corresponding emissions. Interestingly, since the early 2000s, there has been a notable resurgence in coal emissions, driven primarily by increased demand for bituminous coal in Asia. In contrast, sub-bituminous and lignite coals, which are of lower quality, have largely been phased out, highlighting a shift towards higher-grade coal in the global energy market.

How I made this graphic?

Loading required libraries, data import & creating custom functions

Code
# Data Import and Wrangling Tools
library(tidyverse)            # All things tidy

# 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(colorspace)           # Lighten and Darken colours
library(patchwork)            # Combining plots
library(gganimate)            # For animation

# Load data
emissions <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2024/2024-05-21/emissions.csv')

Exploratory Data Analysis & Data Wrangling

Code
# Number of entitites per year - as a graph
emissions |> 
  count(year) |> 
  ggplot(aes(x = year, y = n)) +
  geom_point() + 
  geom_line()

# Emissions total per year

emissions |> 
  group_by(year) |> 
  summarise(total_emissions = sum(total_emissions_MtCO2e)) |> 
  ggplot(aes(x = year, y = total_emissions)) +
  geom_point() +
  geom_line()

emissions |> 
  count(commodity) |> 
  pull(commodity)

coal_levels <- c(
  "Sub-Bituminous Coal",
  "Lignite Coal",
  "Bituminous Coal",
  "Anthracite Coal",
  "Thermal Coal",
  "Metallurgical Coal",
  "Oil & NGL",
  "Natural Gas",
  "Cement"
)


df <- emissions |> 
  group_by(year, commodity) |> 
  summarise(total_emissions = sum(total_emissions_MtCO2e)) |> 
  ungroup() |>
  group_by(year) |> 
  mutate(
    perc = total_emissions/sum(total_emissions),
    comm_2 = if_else(
      str_detect(commodity, "Coal"),
      "Coal",
      commodity
    ),
    commodity = fct(commodity, levels = coal_levels)
  ) |> 
  ungroup() |> 
  group_by(year) |> 
  mutate(yearly_total = sum(total_emissions))

yearly_df <- df |> 
  group_by(year) |> 
  summarise(yearly_total = round(sum(total_emissions), 1))

# Checking if each year exists in the dataset
df |> 
  distinct(year) |> 
  mutate(x = row_number()) |> 
  ggplot(aes(x, year)) +
    geom_col(width = 1)

df |> 
  ggplot(
    aes(
      x = year,
      y = total_emissions,
      fill = commodity
    )
  ) +
  geom_col(position = position_fill()) +
  scale_fill_brewer(palette = "Dark2")

df |> 
  ggplot(
    aes(
      x = year,
      y = total_emissions,
      fill = comm_2
    )
  ) +
  geom_col(position = position_fill())

# Percentage of 2022's emissions in that year
df2 <- emissions |> 
  mutate(commodity = fct(commodity, levels = coal_levels)) |> 
  group_by(year, commodity) |> 
  summarise(total_emissions_co2 = sum(total_emissions_MtCO2e)) |> 
  ungroup() |> 
  group_by(year) |> 
  mutate(
    year_total = sum(total_emissions_co2)
  ) |> 
  ungroup() |> 
  mutate(
    overall_perc = round(100 * year_total / max(year_total), 2)
  )

Visualization Parameters

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

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

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

showtext_auto()

bg_col <- "white"
# Credits for coffeee palette
mypal <- c(
  "#F7CB45FF",
  "#EE8026FF",
  "#DC050CFF",
  "#E8601CFF",
  "#A5170EFF",
  "#E65518FF", 
  "#B4E2FFFF",
  "#7ED7D1FF",
  "#7BAFDEFF"
)

text_col <-  "#00007FFF"
text_hil <-  "#00009BFF"


# 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_hil}'>{github_username}  </span>")
social_caption_2 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{xtwitter};</span> <span style='color: {text_hil}'>{xtwitter_username}</span>")

Annotation Text for the Plot

Code
plot_title <- "Coal's Legacy, Oil's Rise"

plot_caption <- paste0(
  "Data: CarbonMajors    |    Code: @aditya-dahiya (GitHub)"
  )

plot_subtitle <- str_wrap("Shift in contributors to global Cabon dioxide Emissions Sources over Time", 100)

str_view(plot_subtitle)

The static plot

Code
df |> 
  filter(year == 1990) |> 
  
  # Starting the plot
  ggplot(
    mapping = aes(
      x = 1.5,
      y = total_emissions,
      fill = commodity,
      group = commodity
    )
  ) +
  geom_col(
    colour = bg_col
  ) +
  scale_fill_manual(values = mypal) +
  
  # Central Text
  geom_text(
    mapping = aes(label = year),
    x = 0.3,
    y = 0,
    family = "body_font",
    size = 18,
    colour = text_col
  ) +
  geom_text(
    mapping = aes(label = paste0(
      "Total: ",
      number(yearly_total,
             accuracy = 0.1,
             big.mark = ","), 
      " MT")),
    x = 0,
    y = 0,
    family = "body_font",
    colour = text_col
  ) +
  
  # Text Labels 
  geom_text(
    mapping = aes(
      label = paste0(round(100 * perc, 1), "%"),
      size = perc,
      colour = commodity
    ),
    position = position_stack(vjust = 0.5),
    family = "body_font"
  ) +
  geom_text(
    mapping = aes(
      label = str_wrap(commodity, 10, whitespace_only = F),
      x = 2,
      size = perc,
      colour = commodity
    ),
    position = position_stack(vjust = 0.5),
    hjust = "outward",
    lineheight = 0.75,
    family = "caption_font"
  ) +
  
  # Labels
  labs(
    title = plot_title,
    subtitle = plot_subtitle,
    caption = plot_caption
  ) +
  
  # Scales and Coordinates
  scale_colour_manual(values = darken(mypal, 0.75)) +
  
  coord_polar(theta = "y") +
  scale_x_continuous(limits = c(0, 2)) +
  scale_size_continuous(range = c(2, 7)) +
  theme_void(
    base_family = "body_font"
  ) +
  theme(
    legend.position = "none",
    plot.title = element_text(
      hjust = 0.5,
      margin = margin(3,0,0,0, "mm"),
      colour = text_hil,
      size = 18
    ),
    plot.subtitle = element_text(
      hjust = 0.5,
      margin = margin(0,0,0,0, "mm")
    ),
    plot.caption = element_text(
      hjust = 0.5,
      margin = margin(0,0,2,0, "mm")
    )
  )

The Base Animation

Code
g <- df |> 
  
  # Starting the plot
  ggplot(
    mapping = aes(
      x = 1.5,
      y = perc,
      fill = commodity,
      group = commodity
    )
  ) +
  geom_col(
    colour = bg_col
  ) +
  scale_fill_manual(values = mypal) +
  
  # Central Text
  geom_text(
    mapping = aes(label = year),
    x = 0.4,
    y = 0,
    family = "body_font",
    size = 17,
    colour = text_col
  ) +
  
  geom_text(
    mapping = aes(label = paste0(
      "Total: ",
      number(yearly_total,
             accuracy = 0.1,
             big.mark = ","), 
      " MT")),
    x = 0,
    y = 0,
    family = "body_font",
    colour = text_col,
    size = 5
  ) +
  
  # Text Labels 
  geom_text(
    mapping = aes(
      label = paste0(round(100 * perc, 1), "%"),
      size = perc,
      colour = commodity
    ),
    position = position_stack(vjust = 0.5),
    family = "body_font"
  ) +
  geom_text(
    mapping = aes(
      label = str_wrap(commodity, 10, whitespace_only = F),
      x = 2,
      size = perc,
      colour = commodity
    ),
    position = position_stack(vjust = 0.5),
    hjust = "outward",
    lineheight = 0.75,
    family = "caption_font"
  ) +
  
  # Labels
  labs(
    title = plot_title,
    subtitle = plot_subtitle,
    caption = plot_caption
  ) +
  
  # Scales and Coordinates
  scale_colour_manual(values = darken(mypal, 0.75)) +
  
  coord_polar(theta = "y", clip = "off") +
  scale_x_continuous(limits = c(0, 2)) +
  scale_size_continuous(range = c(3, 6)) +
  theme_void(
    base_family = "body_font"
  ) +
  theme(
    legend.position = "none",
    plot.title = element_text(
      hjust = 0.5,
      margin = margin(10,0,2,0, "mm"),
      colour = text_hil,
      size = 36
    ),
    plot.subtitle = element_text(
      hjust = 0.5,
      margin = margin(4,0,0,0, "mm"),
      size = 12,
      colour = text_hil
    ),
    plot.caption = element_text(
      hjust = 0.5,
      margin = margin(0,0,2,0, "mm"),
      size = 12,
      colour = text_hil
    )
  )

g_anim <- g +
  transition_manual(year) +
  ease_aes("linear")

Savings the graphics

Code
anim_save(
  filename = here::here(
    "data_vizs", 
    "tidy_carbon_emissions.gif"
    ),
  animation = g_anim, 
  fps = 10, 
  duration = 30,
  end_pause = 40,
  height = 600, 
  width = 600
)

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