bar plot
sports
Author

Ana Luisa Bodevan

Published

September 23, 2025

Code
######## 1. SETUP

library(pacman)
pacman::p_load(tidyverse, dplyr, showtext, ggtext, ggflags)

# Load data
august <- read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-09-23/fide_ratings_august.csv")
september <- read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-09-23/fide_ratings_september.csv")

# Combine data
all_data <- bind_rows(august, september)

# Federation to ISO2 codes
fed_to_iso2 <- tribble(
  ~fed,  ~iso2,
  "GER", "de",
  "ESP", "es",
  "IND", "in",
  "RUS", "ru",
  "FRA", "fr",
  "USA", "us",
  "SRB", "rs",
  "POL", "pl",
  "HUN", "hu",
  "CZE", "cz"
)

all_data <- all_data %>% left_join(fed_to_iso2, by = "fed")

######## 2. DATA WRANGLING

# Count players by federation and sex
fed_sex_counts <- all_data %>%
  filter(!is.na(iso2), sex %in% c("M", "F")) %>%
  group_by(fed, iso2, sex) %>%
  summarise(players = n(), .groups = "drop") %>%
  group_by(fed, iso2) %>%
  mutate(total = sum(players),
         perc = players / total) %>%
  ungroup() %>%
  # female share for sorting
  group_by(fed, iso2) %>%
  mutate(female_share = perc[sex == "F"]) %>%
  ungroup()


######## 3. PLOT 

font_add("chess", "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf") # for the icons :)
font_add_google("Cinzel", "cinzel")
showtext_auto()

ggplot(fed_sex_counts, aes(x = reorder(fed, female_share), y = perc, fill = sex)) +
  geom_col(width = 0.7, color = "black", linewidth = 0.2) +  # thin black border for chess contrast
  
  # percentage labels inside bars
  geom_text(aes(label = scales::percent(perc, accuracy = 1)),
            position = position_stack(vjust = 0.5),
            color = "white", size = 3.5, family = "cinzel") +
  
  # flags on y-axis
  geom_flag(aes(y = -0.03, country = iso2), size = 12) +
  
  # chess-style colors + ♔♕ labels
  scale_fill_manual(
    values = c("M" = "#335c67", "F" = "#9e2a2b"),
    labels = c("M" = "\u2654 Male",  # ♔
               "F" = "\u2655 Female") # ♕
  ) +
  
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0.05, 0.02))) +
  
  coord_flip() +
  
  labs(
    title = "Gender Distribution of Chess Players by Federation",
    subtitle = "Relative proportions of ♔ male and ♕ female players (Aug–Sep 2025)",
    caption = "Source: FIDE | @anabodevan | #TidyTuesday",
    x = NULL,
    y = "Share of players (%)",
    fill = NULL
  ) +
  
  theme_minimal(base_size = 14) +
  theme(
    plot.background = element_rect(fill = "#faedcd", color = NA),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    
    
    text = element_text(family = "chess"),
    plot.title = element_text(family = "cinzel", face = "bold", size = 20, hjust = 0),
    plot.subtitle = element_text(family = "chess", size = 13, hjust = 0),
    plot.caption = element_text(family = "chess", size = 8, hjust = 1),
    
    axis.text.y = element_blank(),   # hide text labels (flags replace them)
    axis.ticks.y = element_blank(),
    legend.position = "top",
    legend.text = element_text(family = "chess", size = 12)
  )