---
title: "Disaggregating the Sahm Rule"
author: "2Lt., Mark G. Sheppard, M.A., M.P.P., Ph.D. (2025)""
---

```{r}
# Load necessary libraries
library(ggplot2)      # For plotting and customization
library(cowplot)      # For combining ggplot with images
library(magick)       # For handling images with cowplot
library(dplyr)        # For data manipulation
library(tidyr)        # For data reshaping
library(zoo)          # For rolling averages
library(fredr)        # For accessing FRED data

# Set your FRED API key
fredr_set_key("YOUR API KEY")
```

```{r, echo=FALSE, message=FALSE, warning=FALSE, include=FALSE, results='hide'}
# Fetch and process data in a single command
df <- list(
  fredr(series_id = "LNS14000006") %>% select(date, black = value),
  fredr(series_id = "LNU04000003") %>% select(date, white = value),
  fredr(series_id = "LNS14032183") %>% select(date, asian = value),
  fredr(series_id = "LNU04000009") %>% select(date, hispanic = value),
  fredr(series_id = "UNRATE") %>% select(date, unrate = value),
  fredr(series_id = "SAHMREALTIME") %>% select(date, sahm_rule = value),
  fredr(series_id = "USREC") %>% select(date, recession = value)  # Fetch recession indicator
) %>% 
  reduce(full_join, by = "date") %>% 
  mutate(
    # 3-month moving averages
    across(black:hispanic, ~ rollmean(.x, 3, fill = NA, align = "right"), .names = "{.col}_3mo_avg"),
    unrate_3mo_avg = rollmean(unrate, 3, fill = NA, align = "right"),
    
    # 12-month minimum of 3-month UNRATE average
    unrate_min_12mo = rollapply(unrate_3mo_avg, 12, min, fill = NA, align = "right"),
    
    # Sahm Rule differences
    across(black_3mo_avg:hispanic_3mo_avg, ~ .x - unrate_min_12mo, .names = "{.col}_sahm")
  ) %>% 
  select(date, sahm_rule, recession, ends_with("_sahm")) %>% 
  rename(sahm = sahm_rule, black = black_3mo_avg_sahm, white = white_3mo_avg_sahm,
         asian = asian_3mo_avg_sahm, hispanic = hispanic_3mo_avg_sahm) %>%
  
  # Convert to long format for plotting
  pivot_longer(cols = -c(date, sahm, recession), names_to = "category", values_to = "value")

# Clear other objects in environment except 'sahm_'
rm(list = setdiff(ls(), "df")); cat("\014")

# Define the color palette for racial categories
blue_palette <- scale_color_manual(values = c(
  "white" = "#c3e6f7",
  "asian" = "#9ecae1",
  "hispanic" = "#3182bd",
  "black" = "#08519c"
))

# Filter only relevant recession periods (from 1975 onward)
recession_periods <- df %>%
  filter(date >= as.Date("1975-01-01")) %>%
  mutate(
    recession_start = (recession == 1 & lag(recession, default = 0) == 0),
    recession_end = (recession == 0 & lag(recession, default = 1) == 1)
  ) %>%
  filter(recession_start | recession_end) %>%
  mutate(period = cumsum(recession_start)) %>%
  group_by(period) %>%
  summarize(start = min(date), end = max(date)) %>%
  ungroup()
```

```{r, echo=FALSE, message=FALSE, warning=FALSE, include=TRUE, results='hide'}
# Create the plot with recession shading and customized elements
graph <- ggplot(df, aes(x = date, y = value, color = category)) +
  
  # Add recession shading as light grey rectangles for each period
  geom_rect(data = recession_periods, aes(xmin = start, xmax = end, ymin = -Inf, ymax = Inf),
            fill = "grey90", alpha = 0.3, inherit.aes = FALSE) +
  
  # Add the Sahm Rule horizontal reference line first to appear behind other elements
  geom_hline(yintercept = 0.5, linetype = "solid", color = "grey80", size = 0.3) +
  
  # Plot the racial recession lines
  geom_line(size = 0.5) +
  blue_palette +
  
  # Labels and annotations
  labs(
    title = "Racial Recessions",
    subtitle = "The Sahm Recession Indicator, Disaggregated by Race \nShown with Reference Lines and Recessions \nData from 1975 to Present.",
    y = "Recession Indicator",
    color = NULL,  # Remove legend title
    caption = "\nSource: Claudia Sahm, Bureau of Labor Statistics (BLS) \nNote: Indicator based on real-time unemployment rate data, adjusted annually for seasonal factors. \nThe Sahm Recession Indicator signals a recession when the unemployment rate's three-month moving average\nrises by 0.50 percentage points or more relative to the previous 12 months' minimum average.\nAuthor: Mark G. Sheppard"
  ) +
  
  # Recession and Non-Recession indicators
  annotate("text", x = as.Date("1975-01-01"), y = 1, label = "↑ Recession", color = "grey20", hjust = 0, size = 2.4) +
  annotate("text", x = as.Date("1975-01-01"), y = 0, label = "↓ Non-Recession", color = "grey20", hjust = 0, size = 2.3) +
  
  # Note in the middle of the graph
  annotate("text", x = as.Date("1993-01-01"), y = 8.8, 
           label = "By traditional metrics \nthe Black and Hispanic \ncommunity exist in \nperpetual recession", 
           color = "grey60", hjust = 0, size = 2.2, lineheight = 0.9, fontface = "bold") +
  
  # Theme customization
  theme_minimal(base_size = 16) +
  theme(
    plot.title = element_text(face = "bold", size = 13, hjust = 0, vjust = 1, margin = margin(b = 5)),
    plot.subtitle = element_text(size = 7, color = "darkgrey", hjust = 0, margin = margin(t = -5)),
    plot.caption = element_text(size = 6.5, color = "darkgrey", hjust = 0),
    axis.title.y = element_text(size = 8, color = "grey60", margin = margin(r = 10)),
    axis.title.x = element_blank(),
    axis.text.x = element_text(size = 8, color = "grey40"),
    axis.text.y = element_text(size = 8, color = "grey40"),
    panel.grid.major.y = element_line(linetype = "dotted", color = "grey90", linewidth = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank(),
    legend.position = "none",  # Remove legend
    plot.margin = margin(t = 4, r = 3, b = 4, l = 3)
  ) +
  
  # Scale adjustments
  scale_x_date(limits = as.Date(c("1975-01-01", "2024-01-01")), date_breaks = "5 years", date_labels = "%Y") +
  scale_y_continuous(breaks = seq(-10, 12.5, by = 2.5))

# Add external legend image
graph <- ggdraw(graph) + 
  draw_image(image_read("https://raw.githubusercontent.com/markgsheppard/OnlineResources/refs/heads/main/SahmRule-RacialLegend.png"), 
             x = 0.62, y = 0.82, width = 0.36, height = 0.15)

# Display the graph
print(graph)
```

