Skip to content

Instantly share code, notes, and snippets.

@andrewheiss
Created May 22, 2020 19:15
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andrewheiss/69ae7b789c8231c4092db591f056ac75 to your computer and use it in GitHub Desktop.
Save andrewheiss/69ae7b789c8231c4092db591f056ac75 to your computer and use it in GitHub Desktop.
library(tidyverse)  # For ggplot, dplyr, and friends
library(tidyquant)  # For getting financial data from FRED, other places
library(tsibble)    # For working with time-based data
library(fable)      # For time series analysis
library(scales)     # For fun things like comma() and percent()
library(ggtext)     # For text magic in ggplot

# Get data from FRED
# https://fred.stlouisfed.org/series/RSXFSN
data_raw <- tq_get(c("RSXFSN",  # Advance retail sales
                     "USREC"),  # Recessions
                   get = "economic.data",  # Use FRED
                   from = "1967-01-07")  # From first day of data

# Wrangle the recession dates so that we just have start and end dates
recessions_raw <- data_raw %>% 
  filter(symbol == "USREC") %>% 
  mutate(year_month = yearmonth(date)) %>% 
  as_tsibble(index = year_month, key = symbol) %>% 
  mutate(recession_delta = price - lag(price))

recessions <- tibble(start = filter(recessions_raw, recession_delta == 1)$year_month,
                     end = filter(recessions_raw, recession_delta == -1)$year_month)

# Clean up retail sales data
retail_sales <- data_raw %>% 
  filter(symbol == "RSXFSN") %>% 
  filter(date > "1999-12-31") %>% 
  rename(sales = price) %>% 
  mutate(year_month = yearmonth(date)) %>% 
  as_tsibble(index = year_month, key = symbol)

# Decompose sales
sales_model <- retail_sales %>% 
  # Probably best to use multiplicative errors, but then the values are less
  # easily interpretable
  model(ets = ETS(sales ~ error("A") + trend("Ad") + season("A")))

# Convert decomposed data to tidy
sales_model_components <- sales_model %>% 
  components() %>% 
  select(-slope) %>% 
  pivot_longer(cols = c(sales, level, season, remainder),
               names_to = "component", values_to = "value") %>% 
  filter(year_month > "1999-12-31") %>% 
  mutate(is_component = component != "sales") %>% 
  mutate(component = recode(component, sales = "Advance retail sales, raw",
                            level = "Trend",
                            season = "Seasonality",
                            remainder = "Remainder")) %>% 
  mutate(component = fct_inorder(component))

# Plot
ggplot(sales_model_components, aes(x = year_month, y = value)) +
  geom_rect(data = filter(recessions, start > "1999-12-31"), 
            aes(xmin = start, xmax = end, ymin = -Inf, ymax = Inf),
            inherit.aes = FALSE, fill = "#B10DC9", alpha = 0.1) +
  geom_line(aes(color = is_component)) +
  scale_x_date(expand = c(0, 0)) +
  scale_y_continuous(labels = comma) +
  scale_color_manual(values = c("grey60", "#111111")) +
  labs(x = NULL, y = "Millions of dollars",
       caption = "Source: RSXFSN from FRED. Recessions highlighted in <span style='color: #B10DC9;'>purple</span>.") +
  guides(color = FALSE) +
  facet_wrap(vars(component), ncol = 1, scales = "free_y") +
  theme_minimal(base_family = "Halis GR") +
  theme(strip.text = element_text(hjust = 0, face = "bold", size = rel(1.3)),
        plot.caption = element_markdown())

Created on 2020-05-22 by the reprex package (v0.3.0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment