Fourier terms for seasonality

Today let's learn a compact way to put a repeating yearly pattern into a regression model, using an ice-cream shop's monthly sales as the running example.

Bayline Creamery is a small ice-cream shop. Every month since January 2022, it has logged how many tubs it sold. Below are all 48 months, from January 2022 to December 2025, month 1 on the left and month 48 on the right.

Sales climb overall, but every spring sits higher than the months before it, and every autumn dips below them, four times over the four years.

What a Fourier term is: a sine and cosine wave over the seasonal period

Bayline's yearly pattern repeats every 12 months, so statisticians call 12 the seasonal period, written m. The building block for modelling a repeating pattern like this is called a Fourier term: a sine wave and a cosine wave that each complete exactly one cycle over that period.

Before fitting anything, build the 48 months of sales once, so every step from here on can reuse the same data.

RInteractive R
# Build Bayline Creamery's 48 months of tub sales, Jan 2022 to Dec 2025 library(tsibble) library(fable) library(fabletools) library(dplyr) set.seed(42) t <- 1:48 sales <- round(3200 + 40 * t + 900 * sin(2 * pi * t / 12) - 300 * cos(2 * pi * t / 12) + 150 * sin(4 * pi * t / 12) + rnorm(48, 0, 90)) shop <- tsibble(month = yearmonth("2022 Jan") + 0:47, sales = sales, index = month)

  

Now look at the first harmonic on its own, month by month. The first harmonic, k = 1, is a sine wave, written S1, and a cosine wave, written C1, each running through exactly one full cycle over 12 months. For month t, S1 = sin(2 pi t / 12) and C1 = cos(2 pi t / 12). Print both for the twelve months of one cycle to see them as numbers.

RInteractive R
# Look at the first harmonic on its own: one sine wave and one cosine wave over 12 months cycle <- 1:12 S1 <- sin(2 * pi * cycle / 12) C1 <- cos(2 * pi * cycle / 12) data.frame(t = cycle, S1 = round(S1, 3), C1 = round(C1, 3)) #> t S1 C1 #> 1 1 0.500 0.866 #> 2 2 0.866 0.500 #> 3 3 1.000 0.000 #> 4 4 0.866 -0.500 #> 5 5 0.500 -0.866 #> 6 6 0.000 -1.000 #> 7 7 -0.500 -0.866 #> 8 8 -0.866 -0.500 #> 9 9 -1.000 0.000 #> 10 10 -0.866 0.500 #> 11 11 -0.500 0.866 #> 12 12 0.000 1.000

  

S1 starts at 0.5 in month 1, already on its way up, climbs to its peak of 1 in month 3, falls back through zero at month 6, keeps falling to its lowest point of -1 in month 9, then climbs back to zero by month 12. C1 moves a quarter cycle ahead of S1: it starts close to its own peak in month 1, falls to its lowest point in month 6, then climbs back to that same peak by month 12. Together the two waves cover every point in the cycle, one peaking a quarter of a year after the other.

That is what a Fourier term is: two waves, sine and cosine, at a chosen period and harmonic. Bayline's regression will use this pair instead of one separate coefficient for every month.