Home > Graphics > Adding recession shading to time-series graphs

Adding recession shading to time-series graphs

Introduction

Sometimes, I like to augment a time-series graph with shading that indicates periods of recession. In this post, I will show you a simple way to add recession shading to graphs using data provided by import fred. This post also demostrates how to build a complex graph in Stata, beginning with the basic pieces and finishing with a polished product.

The National Bureau of Economic Research (NBER) defines a recession as “a significant decline in economic activity spread across the economy, lasting more than a few months, normally visible in real GDP, real income, employment, industrial production, and wholesale–retail sales.” The NBER maintains a list of turning-point months in which the “peaks” and “troughs” in business activity occurred. A recession is the time between a peak and a trough. As of February 2020, the list of recession dates is located at http://www.nber.org/cycles/cyclesmain.html.

The Federal Reserve Economic Database (FRED), maintained by the Federal Reserve Bank of St. Louis, contains time-series data on thousands of economic indicators from GDP and employment to exchange rates and trade flows. It also contains some utility series, one of which happens to be an indicator variable that indicates whether a given month or quarter belongs to an NBER–defined recession. We will use the import fred command to pull the FRED data directly into Stata.

Finding and importing the data

I first add recession shading to a plot of the unemployment rate. To import the data, I need to know the FRED code for the unemployment rate. I could look it up online, or I could search with the FRED GUI, or I could search using the fredsearch command. Most of the time, I would use the GUI, but for this post I search for it with fredsearch. The command takes a list of keywords as its arguments, so typing

. fredsearch headline unemployment rate

searches for all series in the database that match all the keywords “headline”, “unemployment”, and “rate”. More keywords will narrow a search; fewer keywords will pick up more series.

. fredsearch headline unemployment rate
--------------------------------------------------------------------------------
Series ID          Title                  Data range                Frequency
--------------------------------------------------------------------------------
CPIAUCSL           Consumer Price Ind...  1947-01-01 to 2019-12-01  Monthly
UNRATE             Unemployment Rate      1948-01-01 to 2020-01-01  Monthly
PAYEMS             All Employees, Tot...  1939-01-01 to 2020-01-01  Monthly
USSLIND            Leading Index for ...  1982-01-01 to 2019-12-01  Monthly
CCSA               Continued Claims (...  1967-01-07 to 2020-01-25  Weekly, Endi
> ng Saturday
--------------------------------------------------------------------------------
Total: 5

My search produced five results. It looks like UNRATE is the intended target. I confirm this suspicion with another fredsearch:

. fredsearch UNRATE, detail
--------------------------------------------------------------------------------
UNRATE
--------------------------------------------------------------------------------
Title:                Unemployment Rate
Source:               U.S. Bureau of Labor Statistics
Release:              Employment Situation
Seasonal adjustment:  Seasonally Adjusted
Data range:           1948-01-01 to 2020-01-01
Frequency:            Monthly
Units:                Percent
Last updated:         2020-02-07 07:47:02-06
Notes:                The unemployment rate represents the number of unemploy...
--------------------------------------------------------------------------------
Total: 1

The detail option provides more detail about the matches found by fredsearch.

Next, I need the series that contains the recession indicator. I perform another fredsearch, this time hunting for nber recession.

. fredsearch nber recession, tags(usa monthly)
--------------------------------------------------------------------------------
Series ID          Title                  Data range                Frequency
--------------------------------------------------------------------------------
USREC              NBER based Recessi...  1854-12-01 to 2020-01-01  Monthly
USRECM             NBER based Recessi...  1854-12-01 to 2020-01-01  Monthly
USRECP             NBER based Recessi...  1854-12-01 to 2020-01-01  Monthly
USARECM            OECD based Recessi...  1947-02-01 to 2019-12-01  Monthly
USAREC             OECD based Recessi...  1947-02-01 to 2019-12-01  Monthly
USARECP            OECD based Recessi...  1947-02-01 to 2019-12-01  Monthly
--------------------------------------------------------------------------------
Total: 6

The tags() option restricts the results of the search to series that match the tags. Judicious use of keywords and tags narrows down the results considerably. I use the usa tag to restrict my search to U.S. data and the monthly tag to restrict my search to series with a monthly frequency. I chose a monthly frequency because the unemployment data are reported monthly—see the detail output above. Three series look like they might fit: USREC, USRECM, and USRECP. I choose USRECM because, after a bit more searching, I find that it’s the one that the St. Louis Fed uses.

I import the two series.

. import fred UNRATE USRECM

Summary
--------------------------------------------------------------------------------
Series ID                    Nobs    Date range                Frequency
--------------------------------------------------------------------------------
UNRATE                       865     1948-01-01 to 2020-01-01  Monthly
USRECM                       1982    1854-12-01 to 2020-01-01  Monthly
--------------------------------------------------------------------------------
# of series imported: 2
   highest frequency: Monthly
    lowest frequency: Monthly

The import fred command imports each FRED code listed. It also provides two utility variables, datestr and daten. datestr is a string date variable, while daten is a numeric (daily) date variable. The summary table provides information about each series: the identification code, the number of observations, the date range, and the observation frequency.

A graph with recession shading

Before plotting, I need to run some data management commands. First, I drop all observations for which the unemployment rate is missing. The recession indicator runs from 1854 to the present, while the unemployment series runs only from 1948 to the present. Second, I generate a few useful time variables from the daten variable. Third, I add concise labels to the unemployment rate and recession variables.

. keep if UNRATE < .
(1,117 observations deleted)

. generate datem = mofd(daten)

. tsset datem, monthly
        time variable:  datem, 1948m1 to 2020m1
                delta:  1 month

. label variable UNRATE "Unemployment Rate"

. label variable USRECM "Recession"

The generate datem = mofd(daten) command produces a Stata time variable. The tsset command declares the data to be time-series data. Finally, the label variable command attaches labels to the variables.

Let's draw a preliminary graph of the unemployment rate with tsline:

. tsline UNRATE
graph1

This initial graph simply plots the unemployment rate with all default graph options. The data range goes from about 3% to a little over 10%.

Next, let's draw a preliminary graph of the recession periods. The twoway area plot shades the area underneath a curve, so using it on the recession indicator variable shades the recessions.

. twoway area USRECM datem
graph1

The indicator is 1 if the economy is in recession during the month, and 0 otherwise. From the previous two graphs, the main idea becomes clear: to add recession shading to a graph, simply overlay the unemployment rate plot on top of the recession shading area plot.

We can combine the two graphs. But before doing so, we need to stretch the recession indicator so that the height of the recession bars covers the range of the unemployment rate data. Because the unemployment rate data range from 3 to about 10, I'll stretch the recession indicator to equal 12 during a recession:

. replace USRECM = 12*USRECM
(133 real changes made)

Multiplying the recession indicator by 12 transforms it from a 0–1 variable into a 0–12 variable. Now, it will stretch across the full range of unemployment rates.

Now, we can combine the plots using twoway with each plot bound by ().

. twoway  (area USRECM datem) (tsline UNRATE)

The first line is our area plot; the second line is our line plot. Stata stacks the graphs from first to last, so that the first plot you specify ends up in the background, while the last plot you specify ends up in the foreground. The output looks like this:

graph1

This graph shows off the idea, but the shading is too dark and the axis labels need work. Fortunately, graph twoway has a wide suite of options available to modify the appearance of the graph.

The last step is to make aesthetic adjustments to the graph to improve readability. We change the scheme to select our preferred overall look, and then we modify individual elements of the graph. We use options within twoway area to change the color of the shaded area; these details are changed by specifying the color() option. I choose a light-gray shading, gs14. We use options within tsline to change the appearance of the unemployment rate plot; in particular, the line color is controlled by the lcolor() option. I choose a blue line. Options specified outside the individual plots will affect the entire graph. I adjust the axis titles with xtitle() and ytitle() and adjust the labels with tlabel() and ylabel(). When I am done, the command to run is

. set scheme s1color

. twoway  (area USRECM datem,   color(gs14))          
>         (tsline UNRATE,       lcolor(blue)),       
>         ytitle("Unemployment rate")  xtitle("")     
>         ylabel(0(3)12) tlabel(, format(%tmCCYY))
graph1

Much better. Graphics commands can get complex. Stata has a "type a little, get a little; type a lot, get a lot" philosophy. The more you type, the more control you have over the appearance of the graph.

Another example: Graphs with positive and negative values

As a second example, I add recession shading to a graph of U.S. GDP growth. The FRED code for U.S. real GDP growth is A191RO1Q156NBEA. GDP growth data are quarterly, so we use the quarterly recession indicator variable, which is USRECQM.

I import the data and perform the necessary cleanup.

. import fred A191RO1Q156NBEA USRECQM

Summary
--------------------------------------------------------------------------------
Series ID                    Nobs    Date range                Frequency
--------------------------------------------------------------------------------
A191RO1Q156NBEA              288     1948-01-01 to 2019-10-01  Quarterly
USRECQM                      661     1854-10-01 to 2019-10-01  Quarterly
--------------------------------------------------------------------------------
# of series imported: 2
   highest frequency: Quarterly
    lowest frequency: Quarterly

. generate dateq   = qofd(daten)

. tsset dateq, quarterly
        time variable:  dateq, 1854q4 to 2019q4
                delta:  1 quarter

The import fred command imported the data, the generate dateq = qofd(daten) command generated a date variable, and the tsset command declared the data to be time-series data.

The default name of the GDP growth variable is cumbersome, so I rename it. I also give the series a nice label and drop any missing observations.

. rename A191RO1Q156NBEA growth

. label variable growth "real GDP growth"

. keep if growth < .
(373 observations deleted)

The next thing is to set the bounds of the recession shade area. In the previous section, we summarized the unemployment rate and set the bounds manually. This time, I summarize the growth variable and use some of the summarize command's returned results to set the bounds automatically. I create a new variable, recession, that holds a value equal to the maximum growth rate when USRECQM equals one and holds the minimum growth rate when USRECMQ equals zero. Hence, the area shaded will range vertically from the minimum to the maximum observed GDP growth rate.

. summarize growth

    Variable |        Obs        Mean    Std. Dev.       Min        Max
-------------+---------------------------------------------------------
      growth |        288    3.192361    2.565466       -3.9       13.4

. generate recession = r(max) if USREC == 1
(236 missing values generated)

. replace  recession = r(min) if USREC == 0
(236 real changes made)

Let's draw our graph with recession shading, following the same strategy as before:

. twoway  (area recession dateq,    color(gs14))              
>         (tsline growth,           lcolor(blue)),            
>         xtitle("") ytitle("GDP growth rate, %")

The output is

graph1

That doesn't look right. The behavior of twoway area is to fill in the area from the edge of the graph to the origin, which in our case means that it fills from the top down during recessions but also from the bottom up during expansions. The way to fix it is to use the base() option in twoway area.

The base() option selects the value to drop to. Let's summarize growth again and this time store the value of the minimum in a local macro, min.

. summarize growth

    Variable |        Obs        Mean    Std. Dev.       Min        Max
-------------+---------------------------------------------------------
      growth |        288    3.192361    2.565466       -3.9       13.4

. local min = r(min)

We'll use the value stored in min when graphing. Alternatively, we could have looked at the output and manually copied the minimum value into the graph.

With the base value in hand, let's try again.

. set scheme s1color

. twoway  (area recession dateq,   color(gs14)  base(`min'))   
>         (tsline growth,       lcolor(blue)),                
>         xtitle("") ytitle("GDP growth rate, %")              
>         tlabel(, format(%tqCCYY))

Notice that I have specified the option base(`min') in the first line, within the area graph command. The output is

graph1

This looks correct. Substantively, recessions mark off periods of lower-than-usual GDP growth. Not all recessions are associated with negative GDP growth; for example, growth slowed but did not turn negative during the 2001 recession. The recession of 2007–2009 is clearly visible, with deeply negative growth during 2008.

Conclusion

FRED provides a time-series marking U.S. recessions. You can import it as an indicator variable into Stata, then use that indicator variable to draw recession shading in a time-series graph. I demonstrated how to import series using fredsearch and import fred and how to build a complicated graph out of simpler pieces.

Replication code

I walked you through a few commands that did not work to show you when and why to use various options. The essential commands of the session were

Code block 1: recession_graph_unrate.do
clear all

import fred UNRATE USRECM

keep if UNRATE < .
generate datem = mofd(daten)
tsset datem, monthly
label variable UNRATE "Unemployment Rate"
label variable USRECM "Recession"

replace USRECM = 12*USRECM

twoway (area USRECM datem, color(gs14))               ///
       (tsline UNRATE,    lcolor(blue)),              ///
       xtitle("") ytitle("Unemployment rate")         ///
       ylabel(0(3)12) tlabel(, format(%tmCCYY))
Code block 2: recession_graph_growth.do
clear all

import fred A191RO1Q156NBEA USRECQM
generate dateq = qofd(daten)
tsset dateq, quarterly

rename A191RO1Q156NBEA growth
label variable growth "real GDP growth"
keep if growth < .

summarize growth
generate recession = r(max) if USREC == 1
replace recession  = r(min) if USREC == 0
local min = r(min)

set scheme s1color
twoway (area recession dateq, color(gs14) base(‘min’))   ///
       (tsline growth,  lcolor(blue)),                   ///
       xtitle("") ytitle("GDP growth rate, %")           ///
       tlabel(, format(%tqCCYY))
Categories: Graphics Tags: ,