• Steven Ponce
  • About
  • Data Visualizations
  • Projects
  • Resume
  • Email

On this page

  • Steps to Create this Graphic
    • 1. Load Packages & Setup
    • 2. Read in the Data
    • 3. Examine the Data
    • 4. Tidy Data
    • 5. Visualization Parameters
    • 6. Plot
    • 7. Save
    • 8. Session Info
    • 9. GitHub Repository
    • 10. References
    • 11. Custom Functions Documentation

Half of Scotland’s baby boys once shared just 18 names

  • Show All Code
  • Hide All Code

  • View Source

That number has climbed to 77 since 1974, narrowing a gap that once made girls’ names almost twice as varied.

TidyTuesday
Data Visualization
R Programming
2026
How many distinct names it takes to account for half of Scotland’s babies each year, showing boys’ name diversity quadrupled from 18 (1974) to 77 (2025) and nearly closed a long-standing gap with girls. The metric is redaction- and population-robust across a 50-year series. Built in R with ggplot2, ggtext, and camcorder.
Author

Steven Ponce

Published

June 13, 2026

Figure 1: Line chart titled “Half of Scotland’s baby boys once shared just 18 names.” The vertical axis shows the number of distinct names needed to account for half of all babies born each year from 1974 to 2025, with separate lines for boys and girls, and the gap between them shaded. In 1974, just 18 names accounted for half of baby boys, compared with 35 for girls, making girls’ names about 1.9 times as varied. Boys’ name diversity then climbed steeply to 77 by 2025 while girls’ rose more gently to 85; the two lines reached parity in 2017 at 65 names each before the gap reopened slightly. Both sexes became far more varied overall, but the long-standing gap in name diversity between boys and girls nearly closed. Source: National Records of Scotland.

Steps to Create this Graphic

1. Load Packages & Setup

Show code
```{r}
#| label: load
#| warning: false
#| message: false      
#| results: "hide"     

## 1. LOAD PACKAGES & SETUP ----
suppressPackageStartupMessages({
if (!require("pacman")) install.packages("pacman")
pacman::p_load(
    tidyverse, ggtext, showtext, janitor, ggrepel,      
    scales, glue, skimr
    )
})

### |- figure size ----          
camcorder::gg_record(
  dir    = here::here("temp_plots"),
    device = "png",
    width  = 8,
    height = 6,
    units  = "in",
    dpi    = 320
)

# Source utility functions
suppressMessages(source(here::here("R/utils/fonts.R")))
source(here::here("R/utils/social_icons.R"))
source(here::here("R/utils/image_utils.R"))
source(here::here("R/themes/base_theme.R"))
```

2. Read in the Data

Show code
```{r}
#| label: read
#| include: true
#| eval: true
#| warning: false

tt <- tidytuesdayR::tt_load(2026, week = 24)
scotland_names <- tt$scotland_names |> clean_names()
rm(tt)
```

3. Examine the Data

Show code
```{r}
#| label: examine
#| include: true
#| eval: true
#| results: 'hide'
#| warning: false

glimpse(scotland_names)
```

4. Tidy Data

Show code
```{r}
#| label: tidy
#| warning: false

### |- names needed to cover half of births, per year & sex (n50) ----
## n50 = the number of distinct names that together account for the first 50%
## of babies. It is redaction-robust (the 50% point sits far above the
## redacted ≤2 tail) and N-robust (independent of falling birth totals).
n50_long <- scotland_names |>
  filter(!is.na(number)) |>
  arrange(year, sex, desc(number)) |>
  group_by(year, sex) |>
  mutate(cum_share = cumsum(number) / sum(number)) |>
  summarise(n50 = sum(cum_share < 0.5) + 1L, .groups = "drop")

### |- wide frame for the gap ribbon ----
ribbon_df <- n50_long |>
  pivot_wider(names_from = sex, values_from = n50) |>
  clean_names() |>
  mutate(ymin = pmin(boy, girl), ymax = pmax(boy, girl))

### |- annotation anchors (derived from data, never estimated) ----
boy_1974   <- ribbon_df |> filter(year == 1974) |> pull(boy)    
girl_1974  <- ribbon_df |> filter(year == 1974) |> pull(girl)   
ratio_1974 <- round(girl_1974 / boy_1974, 1)                    
par_year   <- 2017L
par_y      <- ribbon_df |> filter(year == par_year) |> pull(boy) 
last_year  <- max(ribbon_df$year)                                
boy_last   <- ribbon_df |> filter(year == last_year) |> pull(boy)  
girl_last  <- ribbon_df |> filter(year == last_year) |> pull(girl) 
```

5. Visualization Parameters

Show code
```{r}
#| label: params
#| include: true
#| warning: false

### |- plot aesthetics ----
clrs <- get_theme_colors(
  palette = list(
    girl   = "#722F37",
    boy    = "#7A7068",
    ribbon = "#722F37",
    ink    = "#2C2825",
    mute   = "#7A7068"
  )
)
col_girl <- clrs$palette$girl
col_boy <- clrs$palette$boy
col_ribbon <- clrs$palette$ribbon
col_ink <- clrs$palette$ink
col_mute <- clrs$palette$mute

### |- titles and caption ----
title_text <- str_glue("Half of Scotland's baby boys once shared just 18 names")

subtitle_text <- str_glue(
  "That number has climbed to **77** since 1974, narrowing a gap that once ",
  "made girls' names almost twice as varied."
)

methods_note <- str_glue(
  "Each line shows how many distinct names are needed to account for half of ",
  "babies born that year."
)

social_caption <- create_social_caption(
  tt_year     = 2026,
  tt_week     = 24,
  source_text = "National Records of Scotland | Names with counts of 2 or fewer are redacted"
)

caption_text <- str_glue("{methods_note}<br>{social_caption}")

### |- fonts ----
setup_fonts()
fonts <- get_font_families()

### |- plot theme ----
base_theme <- create_base_theme(clrs)

weekly_theme <- extend_weekly_theme(
  base_theme,
  theme(
    plot.title = element_markdown(
      family = fonts$title_1, face = "bold", size = rel(1.6),
      color = col_ink, margin = margin(b = 8)
    ),
    plot.subtitle = element_textbox_simple(
      family = fonts$subtitle, size = rel(0.74), color = col_mute,
      lineheight = 1.15, width = unit(1, "npc"), margin = margin(b = 18)
    ),
    plot.caption = element_markdown(
      family = fonts$caption, size = rel(0.45), color = col_mute,
      hjust = 0, margin = margin(t = 16)
    ),
    axis.title.y = element_markdown(family = fonts$text, size = rel(0.85), color = col_mute),
    axis.text = element_markdown(family = fonts$text, color = col_mute),
    panel.grid.major.y = element_line(color = "gray90", linewidth = 0.3),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank(),
    axis.ticks = element_blank(),
    legend.position = "none",
    plot.margin = margin(t = 20, r = 50, b = 16, l = 20)
  )
)

theme_set(weekly_theme)
```

6. Plot

Show code
```{r}
#| label: plot
#| warning: false

### |- plot ----
p <- ggplot(ribbon_df, aes(x = year)) +

  # Geoms
  geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = col_ribbon, alpha = 0.10) +
  geom_line(aes(y = girl), color = col_girl, linewidth = 1.0) +
  geom_line(aes(y = boy), color = col_boy, linewidth = 1.0) +

  # Annotations
  annotate("segment",
    x = 1974, xend = 1974, y = boy_1974, yend = girl_1974,
    color = col_ink, linewidth = 0.5,
    arrow = arrow(ends = "both", length = unit(0.05, "in"), type = "closed")
  ) +
  annotate("text",
    x = 1976.5, y = (boy_1974 + girl_1974) / 2 + 3,
    label = str_glue("Girls {ratio_1974}\u00d7 as varied\nin 1974"),
    family = fonts$text, size = 3.1, color = col_mute,
    hjust = 0, lineheight = 0.95
  ) +
  annotate("point", x = par_year, y = par_y, color = col_ink, size = 1.8) +
  annotate("segment",
    x = 2008, xend = par_year - 0.4, y = 90, yend = par_y + 1.5,
    color = col_mute, linewidth = 0.3
  ) +
  annotate("text",
    x = 2007.5, y = 92,
    label = "Boys and girls reach parity\n2017 (65 vs 65)",
    family = fonts$text, size = 3.1, color = col_mute,
    hjust = 1, lineheight = 0.95
  ) +
  annotate("text",
    x = last_year + 0.5, y = girl_last, label = "Girls",
    family = fonts$text, fontface = "bold", size = 3.4,
    color = col_girl, hjust = 0
  ) +
  annotate("text",
    x = last_year + 0.5, y = boy_last, label = "Boys",
    family = fonts$text, fontface = "bold", size = 3.4,
    color = col_boy, hjust = 0
  ) +
  # Scales
  scale_x_continuous(
    breaks = c(1974, 1985, 1995, 2005, 2015, 2025),
    expand = expansion(mult = c(0.02, 0.10))
  ) +
  scale_y_continuous(
    breaks = seq(0, 80, 20),
    expand = expansion(mult = c(0.04, 0.08))
  ) +
  coord_cartesian(clip = "off") +
  # Labs
  labs(
    x = NULL,
    y = "Names needed to account for<br>half of babies born",
    title = title_text,
    subtitle = subtitle_text,
    caption = caption_text
  )
```

7. Save

Show code
```{r}
#| label: save
#| warning: false

### |-  plot image ----  
save_plot(
  plot = p, 
  type = "tidytuesday", 
  year = 2026, 
  week = 24, 
  width  = 8,
  height = 6,
  )
```

8. Session Info

TipExpand for Session Info
R version 4.5.3 (2026-03-11 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26100)

Matrix products: default
  LAPACK version 3.12.1

locale:
[1] LC_COLLATE=English_United States.utf8 
[2] LC_CTYPE=English_United States.utf8   
[3] LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.utf8    

time zone: America/New_York
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] here_1.0.2      skimr_2.2.2     glue_1.8.0      scales_1.4.0   
 [5] ggrepel_0.9.8   janitor_2.2.1   showtext_0.9-8  showtextdb_3.0 
 [9] sysfonts_0.8.9  ggtext_0.1.2    lubridate_1.9.5 forcats_1.0.1  
[13] stringr_1.6.0   dplyr_1.2.1     purrr_1.2.2     readr_2.2.0    
[17] tidyr_1.3.2     tibble_3.3.1    ggplot2_4.0.3   tidyverse_2.0.0
[21] pacman_0.5.1   

loaded via a namespace (and not attached):
 [1] gtable_0.3.6       httr2_1.2.2        xfun_0.57          htmlwidgets_1.6.4 
 [5] gh_1.5.0           tzdb_0.5.0         vctrs_0.7.3        tools_4.5.3       
 [9] generics_0.1.4     parallel_4.5.3     curl_7.0.0         gifski_1.32.0-2   
[13] pkgconfig_2.0.3    RColorBrewer_1.1-3 S7_0.2.1           lifecycle_1.0.5   
[17] compiler_4.5.3     farver_2.1.2       textshaping_1.0.5  repr_1.1.7        
[21] codetools_0.2-20   snakecase_0.11.1   litedown_0.9       htmltools_0.5.9   
[25] yaml_2.3.12        crayon_1.5.3       pillar_1.11.1      camcorder_0.1.0   
[29] magick_2.9.1       commonmark_2.0.0   tidyselect_1.2.1   digest_0.6.39     
[33] stringi_1.8.7      rsvg_2.7.0         rprojroot_2.1.1    fastmap_1.2.0     
[37] grid_4.5.3         cli_3.6.6          magrittr_2.0.5     base64enc_0.1-6   
[41] withr_3.0.2        rappdirs_0.3.4     bit64_4.6.0-1      timechange_0.4.0  
[45] rmarkdown_2.31     tidytuesdayR_1.3.2 gitcreds_0.1.2     bit_4.6.0         
[49] otel_0.2.0         ragg_1.5.2         hms_1.1.4          evaluate_1.0.5    
[53] knitr_1.51         markdown_2.0       rlang_1.2.0        gridtext_0.1.6    
[57] Rcpp_1.1.1         xml2_1.5.2         vroom_1.7.1        svglite_2.2.2     
[61] rstudioapi_0.18.0  jsonlite_2.0.0     R6_2.6.1           systemfonts_1.3.2 

9. GitHub Repository

TipExpand for GitHub Repo

The complete code for this analysis is available in tt_2026_24.qmd.

For the full repository, click here.

10. References

TipExpand for References
  1. Data Source:
    • TidyTuesday 2026 Week 24: UK Baby Names

11. Custom Functions Documentation

Note📦 Custom Helper Functions

This analysis uses custom functions from my personal module library for efficiency and consistency across projects.

Functions Used:

  • fonts.R: setup_fonts(), get_font_families() - Font management with showtext
  • social_icons.R: create_social_caption() - Generates formatted social media captions
  • image_utils.R: save_plot() - Consistent plot saving with naming conventions
  • base_theme.R: create_base_theme(), extend_weekly_theme(), get_theme_colors() - Custom ggplot2 themes

Why custom functions?
These utilities standardize theming, fonts, and output across all my data visualizations. The core analysis (data tidying and visualization logic) uses only standard tidyverse packages.

Source Code:
View all custom functions → GitHub: R/utils

Back to top

Citation

BibTeX citation:
@online{ponce2026,
  author = {Ponce, Steven},
  title = {Half of {Scotland’s} Baby Boys Once Shared Just 18 Names},
  date = {2026-06-13},
  url = {https://stevenponce.netlify.app/data_visualizations/TidyTuesday/2026/tt_2026_24.html},
  langid = {en}
}
For attribution, please cite this work as:
Ponce, Steven. 2026. “Half of Scotland’s Baby Boys Once Shared Just 18 Names.” June 13. https://stevenponce.netlify.app/data_visualizations/TidyTuesday/2026/tt_2026_24.html.
Source Code
---
title: "Half of Scotland's baby boys once shared just 18 names"
subtitle: "That number has climbed to 77 since 1974, narrowing a gap that once made girls' names almost twice as varied."
description: "How many distinct names it takes to account for half of Scotland's babies each year, showing boys' name diversity quadrupled from 18 (1974) to 77 (2025) and nearly closed a long-standing gap with girls. The metric is redaction- and population-robust across a 50-year series. Built in R with ggplot2, ggtext, and camcorder."
date: "2026-06-13"
author:
  - name: "Steven Ponce"
    url: "https://stevenponce.netlify.app"
citation:
  url: "https://stevenponce.netlify.app/data_visualizations/TidyTuesday/2026/tt_2026_24.html"
categories: ["TidyTuesday", "Data Visualization", "R Programming", "2026"]
tags: [
  "TidyTuesday",
  "Line Chart",
  "Baby Names",
  "Scotland",
  "Name Diversity",
  "Demographics",
  "Time Series",
  "Annotation",
  "ggtext",
  "camcorder",
  "ggplot2",
  "2026"
]
image: "thumbnails/tt_2026_24.png"
format:
  html:
    toc: true
    toc-depth: 5
    code-link: true
    code-fold: true
    code-tools: true
    code-summary: "Show code"
    self-contained: true
    theme: 
      light: [flatly, assets/styling/custom_styles.scss]
      dark: [darkly, assets/styling/custom_styles_dark.scss]
editor_options: 
  chunk_output_type: inline
execute: 
  freeze: true
  cache: true
  error: false
  message: false
  warning: false
  eval: true
---

![Line chart titled "Half of Scotland's baby boys once shared just 18 names." The vertical axis shows the number of distinct names needed to account for half of all babies born each year from 1974 to 2025, with separate lines for boys and girls, and the gap between them shaded. In 1974, just 18 names accounted for half of baby boys, compared with 35 for girls, making girls' names about 1.9 times as varied. Boys' name diversity then climbed steeply to 77 by 2025 while girls' rose more gently to 85; the two lines reached parity in 2017 at 65 names each before the gap reopened slightly. Both sexes became far more varied overall, but the long-standing gap in name diversity between boys and girls nearly closed. Source: National Records of Scotland.](tt_2026_24.png){#fig-1}

### [**Steps to Create this Graphic**]{.mark}

#### [1. Load Packages & Setup]{.smallcaps}

```{r}
#| label: load
#| warning: false
#| message: false      
#| results: "hide"     

## 1. LOAD PACKAGES & SETUP ----
suppressPackageStartupMessages({
if (!require("pacman")) install.packages("pacman")
pacman::p_load(
    tidyverse, ggtext, showtext, janitor, ggrepel,      
    scales, glue, skimr
    )
})

### |- figure size ----          
camcorder::gg_record(
  dir    = here::here("temp_plots"),
    device = "png",
    width  = 8,
    height = 6,
    units  = "in",
    dpi    = 320
)

# Source utility functions
suppressMessages(source(here::here("R/utils/fonts.R")))
source(here::here("R/utils/social_icons.R"))
source(here::here("R/utils/image_utils.R"))
source(here::here("R/themes/base_theme.R"))
```

#### [2. Read in the Data]{.smallcaps}

```{r}
#| label: read
#| include: true
#| eval: true
#| warning: false

tt <- tidytuesdayR::tt_load(2026, week = 24)
scotland_names <- tt$scotland_names |> clean_names()
rm(tt)
```

#### [3. Examine the Data]{.smallcaps}

```{r}
#| label: examine
#| include: true
#| eval: true
#| results: 'hide'
#| warning: false

glimpse(scotland_names)
```

#### [4. Tidy Data]{.smallcaps}

```{r}
#| label: tidy
#| warning: false

### |- names needed to cover half of births, per year & sex (n50) ----
## n50 = the number of distinct names that together account for the first 50%
## of babies. It is redaction-robust (the 50% point sits far above the
## redacted ≤2 tail) and N-robust (independent of falling birth totals).
n50_long <- scotland_names |>
  filter(!is.na(number)) |>
  arrange(year, sex, desc(number)) |>
  group_by(year, sex) |>
  mutate(cum_share = cumsum(number) / sum(number)) |>
  summarise(n50 = sum(cum_share < 0.5) + 1L, .groups = "drop")

### |- wide frame for the gap ribbon ----
ribbon_df <- n50_long |>
  pivot_wider(names_from = sex, values_from = n50) |>
  clean_names() |>
  mutate(ymin = pmin(boy, girl), ymax = pmax(boy, girl))

### |- annotation anchors (derived from data, never estimated) ----
boy_1974   <- ribbon_df |> filter(year == 1974) |> pull(boy)    
girl_1974  <- ribbon_df |> filter(year == 1974) |> pull(girl)   
ratio_1974 <- round(girl_1974 / boy_1974, 1)                    
par_year   <- 2017L
par_y      <- ribbon_df |> filter(year == par_year) |> pull(boy) 
last_year  <- max(ribbon_df$year)                                
boy_last   <- ribbon_df |> filter(year == last_year) |> pull(boy)  
girl_last  <- ribbon_df |> filter(year == last_year) |> pull(girl) 

```

#### [5. Visualization Parameters]{.smallcaps}

```{r}
#| label: params
#| include: true
#| warning: false

### |- plot aesthetics ----
clrs <- get_theme_colors(
  palette = list(
    girl   = "#722F37",
    boy    = "#7A7068",
    ribbon = "#722F37",
    ink    = "#2C2825",
    mute   = "#7A7068"
  )
)
col_girl <- clrs$palette$girl
col_boy <- clrs$palette$boy
col_ribbon <- clrs$palette$ribbon
col_ink <- clrs$palette$ink
col_mute <- clrs$palette$mute

### |- titles and caption ----
title_text <- str_glue("Half of Scotland's baby boys once shared just 18 names")

subtitle_text <- str_glue(
  "That number has climbed to **77** since 1974, narrowing a gap that once ",
  "made girls' names almost twice as varied."
)

methods_note <- str_glue(
  "Each line shows how many distinct names are needed to account for half of ",
  "babies born that year."
)

social_caption <- create_social_caption(
  tt_year     = 2026,
  tt_week     = 24,
  source_text = "National Records of Scotland | Names with counts of 2 or fewer are redacted"
)

caption_text <- str_glue("{methods_note}<br>{social_caption}")

### |- fonts ----
setup_fonts()
fonts <- get_font_families()

### |- plot theme ----
base_theme <- create_base_theme(clrs)

weekly_theme <- extend_weekly_theme(
  base_theme,
  theme(
    plot.title = element_markdown(
      family = fonts$title_1, face = "bold", size = rel(1.6),
      color = col_ink, margin = margin(b = 8)
    ),
    plot.subtitle = element_textbox_simple(
      family = fonts$subtitle, size = rel(0.74), color = col_mute,
      lineheight = 1.15, width = unit(1, "npc"), margin = margin(b = 18)
    ),
    plot.caption = element_markdown(
      family = fonts$caption, size = rel(0.45), color = col_mute,
      hjust = 0, margin = margin(t = 16)
    ),
    axis.title.y = element_markdown(family = fonts$text, size = rel(0.85), color = col_mute),
    axis.text = element_markdown(family = fonts$text, color = col_mute),
    panel.grid.major.y = element_line(color = "gray90", linewidth = 0.3),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank(),
    axis.ticks = element_blank(),
    legend.position = "none",
    plot.margin = margin(t = 20, r = 50, b = 16, l = 20)
  )
)

theme_set(weekly_theme)
```

#### [6. Plot]{.smallcaps}

```{r}
#| label: plot
#| warning: false

### |- plot ----
p <- ggplot(ribbon_df, aes(x = year)) +

  # Geoms
  geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = col_ribbon, alpha = 0.10) +
  geom_line(aes(y = girl), color = col_girl, linewidth = 1.0) +
  geom_line(aes(y = boy), color = col_boy, linewidth = 1.0) +

  # Annotations
  annotate("segment",
    x = 1974, xend = 1974, y = boy_1974, yend = girl_1974,
    color = col_ink, linewidth = 0.5,
    arrow = arrow(ends = "both", length = unit(0.05, "in"), type = "closed")
  ) +
  annotate("text",
    x = 1976.5, y = (boy_1974 + girl_1974) / 2 + 3,
    label = str_glue("Girls {ratio_1974}\u00d7 as varied\nin 1974"),
    family = fonts$text, size = 3.1, color = col_mute,
    hjust = 0, lineheight = 0.95
  ) +
  annotate("point", x = par_year, y = par_y, color = col_ink, size = 1.8) +
  annotate("segment",
    x = 2008, xend = par_year - 0.4, y = 90, yend = par_y + 1.5,
    color = col_mute, linewidth = 0.3
  ) +
  annotate("text",
    x = 2007.5, y = 92,
    label = "Boys and girls reach parity\n2017 (65 vs 65)",
    family = fonts$text, size = 3.1, color = col_mute,
    hjust = 1, lineheight = 0.95
  ) +
  annotate("text",
    x = last_year + 0.5, y = girl_last, label = "Girls",
    family = fonts$text, fontface = "bold", size = 3.4,
    color = col_girl, hjust = 0
  ) +
  annotate("text",
    x = last_year + 0.5, y = boy_last, label = "Boys",
    family = fonts$text, fontface = "bold", size = 3.4,
    color = col_boy, hjust = 0
  ) +
  # Scales
  scale_x_continuous(
    breaks = c(1974, 1985, 1995, 2005, 2015, 2025),
    expand = expansion(mult = c(0.02, 0.10))
  ) +
  scale_y_continuous(
    breaks = seq(0, 80, 20),
    expand = expansion(mult = c(0.04, 0.08))
  ) +
  coord_cartesian(clip = "off") +
  # Labs
  labs(
    x = NULL,
    y = "Names needed to account for<br>half of babies born",
    title = title_text,
    subtitle = subtitle_text,
    caption = caption_text
  )
```

#### [7. Save]{.smallcaps}

```{r}
#| label: save
#| warning: false

### |-  plot image ----  
save_plot(
  plot = p, 
  type = "tidytuesday", 
  year = 2026, 
  week = 24, 
  width  = 8,
  height = 6,
  )
```

#### [8. Session Info]{.smallcaps}

::: {.callout-tip collapse="true"}
##### Expand for Session Info

```{r, echo = FALSE}
#| eval: true
#| warning: false

sessionInfo()
```
:::

#### [9. GitHub Repository]{.smallcaps}

::: {.callout-tip collapse="true"}
##### Expand for GitHub Repo

The complete code for this analysis is available in [`tt_2026_24.qmd`](https://github.com/poncest/personal-website/blob/master/data_visualizations/TidyTuesday/2026/tt_2026_24.qmd).

For the full repository, [click here](https://github.com/poncest/personal-website/).
:::

#### [10. References]{.smallcaps}

::: {.callout-tip collapse="true"}
##### Expand for References
1.  **Data Source:**
    -   TidyTuesday 2026 Week 24: [UK Baby Names](https://github.com/rfordatascience/tidytuesday/blob/main/data/2026/2026-06-16/readme.md)

:::


#### [11. Custom Functions Documentation]{.smallcaps}

::: {.callout-note collapse="true"}
##### 📦 Custom Helper Functions

This analysis uses custom functions from my personal module library for efficiency and consistency across projects.

**Functions Used:**

-   **`fonts.R`**: `setup_fonts()`, `get_font_families()` - Font management with showtext
-   **`social_icons.R`**: `create_social_caption()` - Generates formatted social media captions
-   **`image_utils.R`**: `save_plot()` - Consistent plot saving with naming conventions
-   **`base_theme.R`**: `create_base_theme()`, `extend_weekly_theme()`, `get_theme_colors()` - Custom ggplot2 themes

**Why custom functions?**\
These utilities standardize theming, fonts, and output across all my data visualizations. The core analysis (data tidying and visualization logic) uses only standard tidyverse packages.

**Source Code:**\
View all custom functions → [GitHub: R/utils](https://github.com/poncest/personal-website/tree/master/R)
:::

© 2024 Steven Ponce

Source Issues