1,2,3,4 or is that 0,1,2,3?
Over on Twitter, Fintwit relives this epic debate on a bodybuilding forum about how many days are in a week. The Fintwit question, did the recession start in February or March 2020? I stand with Francis Diebold on this one!
This is the fintwit version arguing about how many days there are in week https://t.co/bK48taGcRm
— 📈 Len Kiefer 📊 (@lenkiefer) June 16, 2020
Though it’s easy to get turned around on this one and I’m sure I’ve been inconsistent in the past. Hopefully I can make it through this post.
Also on Twitter, I see another cool package. This one mdthemes from Thomas Neitmann which allows you to easily incorporate markdown into your ggplots with R.
Chart Remix
Speaking of recession lengths and mdthemes, let’s remix the chart from my LinkedIn Post on Expanding Expansions, Contracting Recessions. We’ll also be sure to count precisely.
library(sqldf)
library(ggrepel)
library(tidyverse)
library(mdthemes)
library(lubridate)
Data prep code
#####################################################################################
## Make Recession Data Frame ##
# based on NBER dates: https://www.nber.org/cycles.html
#####################################################################################
recessions.df = read.table(textConnection(
"Peak, Trough
1857-06-01, 1858-12-01
1860-10-01, 1861-06-01
1865-04-01, 1867-12-01
1869-06-01, 1870-12-01
1873-10-01, 1879-03-01
1882-03-01, 1885-05-01
1887-03-01, 1888-04-01
1890-07-01, 1891-05-01
1893-01-01, 1894-06-01
1895-12-01, 1897-06-01
1899-06-01, 1900-12-01
1902-09-01, 1904-08-01
1907-05-01, 1908-06-01
1910-01-01, 1912-01-01
1913-01-01, 1914-12-01
1918-08-01, 1919-03-01
1920-01-01, 1921-07-01
1923-05-01, 1924-07-01
1926-10-01, 1927-11-01
1929-08-01, 1933-03-01
1937-05-01, 1938-06-01
1945-02-01, 1945-10-01
1948-11-01, 1949-10-01
1953-07-01, 1954-05-01
1957-08-01, 1958-04-01
1960-04-01, 1961-02-01
1969-12-01, 1970-11-01
1973-11-01, 1975-03-01
1980-01-01, 1980-07-01
1981-07-01, 1982-11-01
1990-07-01, 1991-03-01
2001-03-01, 2001-11-01
2007-12-01, 2009-06-01
2020-02-01, 9999-01-01"), sep=',',
colClasses=c('Date', 'Date'), header=TRUE)
df<- data.frame(date=seq.Date(as.Date("1857-01-01"),
as.Date("2020-06-01"), by="1 month"))
rdf <- recessions.df %>%
mutate(TroughLag = lag(Trough), # find last trough
PeakLag = lag(Peak) # find last peak
)
# Merge with sqldf
output <- sqldf("select * from df left join rdf
on (df.date>=rdf.Peak and df.date <= rdf.Trough or
(df.date > rdf.TroughLag and df.date <= rdf.Peak)) ")
outdf <-
mutate(filter(output,!is.na(TroughLag)),
expand=ifelse(date>=Peak, "Recession","Expansion"),
d1=ifelse(expand=="Recession",Peak %m+% months(1), TroughLag %m+% months(1)),
d2=ifelse(expand=="Recession",Trough, Peak %m-% months(0))) %>%
mutate(d1=as.Date(d1, origin = lubridate::origin),
d2=as.Date(d2, origin = lubridate::origin)) %>%
mutate(name=paste0(expand, " ",
as.character(d1, format="%b %Y"), " : ",
as.character(d2, format="%b %Y")
)) %>%
mutate(contraction = interval(Peak, Trough) %/% months(1), # Peak to Trough
expansion = interval(TroughLag, Peak) %/% months(1), # Previous Trough to this Peak
cycle1 = interval(TroughLag, Trough) %/% months(1), # Trough from previous Trough
cycle2 = interval(PeakLag, Peak) %/% months(1)) # Peak from previous Peak
outdf2 <-
outdf %>% group_by(name, expand) %>%
summarize(start.date=min(date),
end.date=max(date),
contraction_peak_to_trough=mean(contraction),
expansion_previous_trough_to_this_peak=mean(expansion),
cycle_trough_from_previous_trough=mean(cycle1),
cycle_peak_from_previous_peak=mean(cycle2)) %>%
ungroup() %>% arrange(start.date) %>%
mutate(duration =ifelse(expand=="Recession",
contraction_peak_to_trough,
expansion_previous_trough_to_this_peak)) %>%
arrange(start.date) %>% filter(!is.na(expand) ) %>%
rename(type=expand)
First let’s recreate the plot we made before, without using mdthemes.
#####################################################################################
## Make Plot No mdthemes ##
#####################################################################################
ggplot(data = outdf2 %>% filter(!is.na(type)),
aes(x=start.date, xend=end.date,
y=duration, yend=duration, label=name,color=type))+
scale_fill_manual(name="Expansion or Recession", values= c("#4575b4", "#d73027"))+
scale_color_manual(name="Expansion or Recession", values= c("#4575b4", "#d73027"))+
theme_minimal(base_size=9)+
theme(legend.position="bottom",
plot.caption=element_text(hjust=0,size=rel(0.8)) )+
geom_segment(size=1.1)+
scale_y_continuous(breaks=seq(0,130,10),limits=c(0,130),expand=c(0,0),sec.axis=dup_axis())+
# even with ggrepel, labeling all points gets crowded
geom_text_repel(data= outdf2 %>%
filter(duration>40 | (year(start.date)> 1969 | year(start.date) < 1860)
), size=3)+
stat_smooth(method="lm", fill=NA, linetype=2, alpha=0.35)+
#geom_rug(data=outdf,sides="b", inherit.aes=FALSE,aes(x=date,color=expand))+
labs(x="Date",y="Duration of U.S. Expansion/Recession in Months",
title="Expansions Expand, Recessions Contract",
subtitle="Duration of U.S. expansions/recessions over time\n",
caption="@lenkiefer Source: NBER recession dates as of June 16, 2020 http://www.nber.org/cycle.html\n\nSegments extend from expansion/recession start to end date on x axis, y axis equals length of expansion/recession.\nDotted lines regression fit to expansion/recession: duration ~ start.date")
Now let’s use mdthemes to enhance the plot. We’ll use the markdown syntax to make the title colors correspond to recessions (red) and expansions (blue).
We will use the mdthemes::as_md_theme
function to wrap theme_minimal and automagically allow us to use text styling within our title, subtitle, and caption calls to ggplot2
.
#####################################################################################
## Make Plot with mdthemese##
#####################################################################################
ggplot(data = outdf2,# %>% filter(!is.na(type)),
aes(x=start.date, xend=end.date,
y=duration, yend=duration, label=name,color=type))+
scale_fill_manual(name="Expansion or Recession", values= c("#4575b4", "#d73027"))+
scale_color_manual(name="Expansion or Recession", values= c("#4575b4", "#d73027"))+
as_md_theme(theme_minimal(base_size=9)+
theme(legend.position="bottom",
plot.caption=element_text(hjust=0,size=rel(0.8)) ))+
geom_segment(size=1.1)+
scale_y_continuous(breaks=seq(0,130,10),limits=c(0,130),expand=c(0,0),sec.axis=dup_axis())+
# even with ggrepel, labeling all points gets crowded
geom_text_repel(data= outdf2 %>%
filter(duration>40 | (year(start.date)> 1969 | year(start.date) < 1860)
), size=3,show.legend = FALSE)+
stat_smooth(method="lm", fill=NA, linetype=2, alpha=0.35)+
#geom_rug(data=outdf,sides="b", inherit.aes=FALSE,aes(x=date,color=expand))+
labs(x="Date",y="Duration of U.S. Expansion/Recession in Months",
title=paste0("<span style = 'color:#4575b4'>Expansions Expand</span>,",
"<span style = 'color:#d73027'> Recessions Contract</span>"),
subtitle="Duration of U.S. expansions/recessions over time\n",
caption="<span style= 'color:#fe5305'>**@lenkiefer**</span> Source: NBER recession dates as of June 16, 2020<br>Segments extend from expansion/recession start to end date on x axis, y axis equals length of expansion/recession.<br>Dotted lines regression fit to expansion/recession: duration ~ start.date")