## ----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")