Seasonal adjustment with X-13 and STL

Today let's understand what a seasonally adjusted number actually is, and why the agencies that publish it never let it stand in for a forecast.

Victoria's monthly turnover for cafes, restaurants and takeaway food services is a real series the Australian Bureau of Statistics has tracked every month since April 1982. Over 441 months it climbs from $81.3 million a month to $1,066.2 million a month.

Here is the whole series, plotted in the order the months actually happened.

Look at the very end of that line. November 2018 closes at $981.8 million, and December 2018 jumps to $1,066.2 million, a rise of 8.6 percent in a single month. Is that real growth, or the same jump every December brings once people start spending for Christmas?

What season_adjust means, and how STL produces it

STL splits a series into three parts that add back up to the original number: a trend, the slow-moving level; a season_year, the part of the pattern that repeats every twelve months, tied to the calendar rather than to the economy; and a remainder, whatever is left over once both of those are taken out.

Fit STL on the Victoria cafe series, then look at the last three months of 2018.

RInteractive R
# Build the Victoria cafe series, fit STL, and read October to December 2018 library(tsibble) library(tsibbledata) library(dplyr) library(feasts) library(fabletools) cafe <- tsibbledata::aus_retail |> filter(State == "Victoria", Industry == "Cafes, restaurants and takeaway food services") fit <- cafe |> model(STL(Turnover ~ trend(window = 21) + season(window = 11), robust = TRUE)) comp <- components(fit) result <- comp |> filter(Month >= yearmonth("2018 Oct"), Month <= yearmonth("2018 Dec")) |> as_tibble() |> transmute(Month = as.character(Month), Turnover = round(Turnover, 1), season_year = round(season_year, 1), season_adjust = round(season_adjust, 1)) print(as.data.frame(result), row.names = FALSE) #> Month Turnover season_year season_adjust #> 2018 Oct 960.0 11.9 948.1 #> 2018 Nov 981.8 28.5 953.3 #> 2018 Dec 1066.2 93.9 972.3

  

season_adjust is Turnover with the season_year part taken out, nothing more. It is computed as Turnover - season_year. Since Turnover is the sum of all three parts, season_adjust is really trend plus remainder: everything except the calendar effect.

Look at December. Turnover that month is 1066.2, and season_year is 93.9, so season_adjust comes out at 1066.2 minus 93.9, which is 972.3. That 93.9 is STL's estimate of how much of a typical December's turnover is just "it's December", built from every December in the 37 years of data. Take it out, and what is left, 972.3, is the number this lesson is really about.