## ----chunk-options, include = FALSE-------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5
)

## ----setup--------------------------------------------------------------------
library(pressfreedom.data)
library(dplyr)
library(ggplot2)
library(tidyr)
library(patchwork)
library(sf)

data(rwb_standardized)

## ----us-setup-----------------------------------------------------------------
us_rank <- rwb_standardized |>
  filter(country_en == "United States", !is.na(rank)) |>
  arrange(year_n)

us_score <- rwb_standardized |>
  filter(country_en == "United States", year_n >= 2013, !is.na(score)) |>
  arrange(year_n)

## ----us-charts, fig.alt = "Two line charts side by side: the United States' press freedom rank from 2002 to 2026 on the left, and its score from 2013 to 2026 on the right."----
p_us_rank <- ggplot(us_rank, aes(x = year_n, y = rank)) +
  geom_line() +
  geom_point() +
  scale_y_reverse() +
  labs(x = "Year", y = "Rank (1 = most free)", title = "Rank, 2002-2026")

p_us_score <- ggplot(us_score, aes(x = year_n, y = score)) +
  geom_line() +
  geom_point() +
  labs(
    x = "Year",
    y = "Score (100 = most free)",
    title = "Score, 2013-2026"
  )

p_us_rank + p_us_score

## ----compare-setup------------------------------------------------------------
compare_countries <- c(
  "United States", "China", "Brazil", "Nigeria", "Japan", "Germany"
)

compare_score <- rwb_standardized |>
  filter(country_en %in% compare_countries, year_n >= 2013, !is.na(score)) |>
  arrange(country_en, year_n)

compare_rank <- rwb_standardized |>
  filter(country_en %in% compare_countries, !is.na(rank)) |>
  arrange(country_en, year_n)

## ----compare-score-chart, fig.alt = "Line chart comparing press freedom scores for the United States, China, Brazil, Nigeria, Japan, and Germany from 2013 to 2026."----
# Order the legend to match each country's end-of-series score, top to
# bottom, instead of the alphabetical default
compare_score <- compare_score |>
  mutate(country_en = forcats::fct_reorder2(country_en, year_n, score))

ggplot(compare_score, aes(x = year_n, y = score, color = country_en)) +
  geom_line() +
  geom_point() +
  labs(
    x = "Year",
    y = "Score (100 = most free)",
    color = "Country",
    title = "Press Freedom Score, 2013-2026"
  )

## ----compare-rank-chart, fig.alt = "Bump chart comparing press freedom rank for the United States, China, Brazil, Nigeria, Japan, and Germany from 2002 to 2026, with a reversed y-axis.", fig.height = 6----
# `.desc = FALSE` because the y-axis is reversed below (rank 1 = best, drawn
# at the top); ordering the legend ascending by rank keeps it in the same
# top-to-bottom order as the lines at their right-hand endpoints
compare_rank <- compare_rank |>
  mutate(country_en = forcats::fct_reorder2(
    country_en, year_n, rank,
    .desc = FALSE
  ))

ggplot(compare_rank, aes(x = year_n, y = rank, color = country_en)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  scale_y_reverse() +
  labs(
    x = "Year",
    y = "Rank (1 = most free)",
    color = "Country",
    title = "Press Freedom Rank, 2002-2026"
  )

## ----dimensions_setup---------------------------------------------------------
us_dims <- rwb_standardized |>
  filter(country_en == "United States", year_n >= 2022) |>
  select(
    year_n, score, political_context, economic_context,
    legal_context, social_context, safety
  ) |>
  tidyr::pivot_longer(
    cols = -"year_n",
    names_to = "dimension",
    values_to = "value"
  )

## ----dimensions_chart, fig.alt = "Line chart for the United States' overall score and five sub-dimensions from 2022 to 2026."----
# Order the legend to match each dimension's end-of-series value
us_dims <- us_dims |>
  mutate(dimension = forcats::fct_reorder2(dimension, year_n, value))

ggplot(us_dims, aes(x = year_n, y = value, color = dimension)) +
  geom_line() +
  geom_point() +
  labs(
    x = "Year",
    y = "Score (higher is better)",
    color = "Dimension",
    title = "United States: Overall Score and Sub-Dimensions, 2022-2026"
  )

## ----zones_setup--------------------------------------------------------------
zone_means <- rwb_standardized |>
  filter(year_n >= 2013, !is.na(zone), !is.na(score)) |>
  group_by(zone, year_n) |>
  summarise(mean_score = mean(score), .groups = "drop")

global_mean <- rwb_standardized |>
  filter(year_n >= 2013, !is.na(score)) |>
  group_by(year_n) |>
  summarise(mean_score = mean(score), .groups = "drop")

## ----zones_chart, fig.alt = "Line chart of mean press freedom score by geographic zone from 2013 to 2026, with a black line showing the global mean across all countries."----
zone_colors <- c(
  setNames(scales::hue_pal()(dplyr::n_distinct(zone_means$zone)), sort(unique(zone_means$zone))),
  "Global mean" = "black"
)

# Order the legend (via `breaks`) to match each line's end-of-series value,
# combining the zones and the global mean into one ranking
legend_order <- bind_rows(
  zone_means |>
    filter(year_n == max(year_n)) |>
    select("zone", "mean_score"),
  global_mean |>
    filter(year_n == max(year_n)) |>
    transmute(zone = "Global mean", mean_score)
) |>
  arrange(desc(mean_score)) |>
  pull(zone)

ggplot(mapping = aes(x = year_n, y = mean_score, color = zone)) +
  geom_line(data = zone_means) +
  geom_point(data = zone_means) +
  geom_line(
    data = global_mean,
    aes(color = "Global mean"),
    linewidth = 1
  ) +
  geom_point(data = global_mean, aes(color = "Global mean")) +
  scale_color_manual(values = zone_colors, breaks = legend_order) +
  labs(
    x = "Year",
    y = "Mean score",
    color = "Zone",
    title = "Mean Press Freedom Score by Region, 2013-2026"
  )

## ----map_setup----------------------------------------------------------------
world <- rnaturalearth::ne_countries(scale = "small", returnclass = "sf") |>
  # Drop Antarctica, keeps the map focused on populated landmass
  dplyr::filter(.data$continent != "Antarctica")

scores_2025 <- rwb_standardized |>
  filter(year_n == 2025, !is.na(score)) |>
  select("iso", "score")

world_scores <- world |>
  left_join(scores_2025, by = c("iso_a3" = "iso"))

## ----map_chart, fig.alt = "World map colored by press freedom score in 2025, using the Robinson projection. Countries range from dark red (low score, less free) to light yellow (high score, more free); a handful of small territories not rated by RSF are shown in grey.", fig.width = 7, fig.height = 4.6----
ggplot(world_scores) +
  geom_sf(aes(fill = score), color = NA) +
  scale_fill_viridis_c(
    option = "rocket",
    na.value = "grey70",
    name = "Score (100 = most free)",
    guide = guide_colorbar(
      title.position = "top",
      title.hjust = 0.5,
      barwidth = unit(120, "pt"),
      barheight = unit(6, "pt")
    )
  ) +
  coord_sf(
    crs = "+proj=robin",
    # Crop near the poles (Antarctica already dropped) to remove
    # the empty white space a full-globe Robinson projection leaves
    # above and below the populated landmass
    default_crs = sf::st_crs(4326),
    xlim = c(-180, 180),
    ylim = c(-60, 85),
    expand = FALSE
  ) +
  theme_void() +
  theme(
    plot.title = element_text(hjust = 0.5),
    legend.position = "bottom",
    plot.margin = margin(0, 0, 0, 0)
  ) +
  labs(title = "Press Freedom Score by Country, 2025")

