geotheory
geotheory

Reputation: 23630

Decomposing weekly data fails with "Error in decompose: time series has no or less than 2 periods"

I need to decompose weekly data and whatever I do errors with: time series has no or less than 2 periods. All other questions I've read on this so not seem to fix for me. Here is a reproducible example with explicit trend, cyclical, and noise components. Very grateful for help to identify what I'm doing wrong.

require(dplyr)

degrees_to_radians = \(x) pi * x / 180

d = tibble(date = Sys.Date() - 13013:0) |> 
  filter(as.numeric(date) %% 7 == 0) |> 
  mutate(trend = EuStockMarkets[1:n(),1],
         i = as.numeric(date - lubridate::floor_date(date, 'year')),
         cyc = 100 * cos(degrees_to_radians(i)),
         noise = 50 * rnorm(n()),
         val = trend + cyc + noise) |> 
  select(date, val)

plot(d, type='l')

enter image description here

t = ts(d)
decompose(t)
#> Error in decompose(t): time series has no or less than 2 periods

# explicit frequency
t = as.ts(d$val, start = min(d$date), end = max(d$date), frequency = 365/7)
decompose(t)
#> Error in decompose(t): time series has no or less than 2 periods

# try via xts
x = xts::xts(d[,-1], order.by = d$date, dateFormat = "Date", frequency = 365/7)

plot(x)

enter image description here

decompose(as.ts(x))
#> Error in decompose(as.ts(x)): time series has no or less than 2 periods

# try 5 years
decompose(as.ts(tail(x, 260))) 
#> Error in decompose(as.ts(tail(x, 260))): time series has no or less than 2 periods
Created on 2022-06-16 by the reprex package (v2.0.1)

Upvotes: 1

Views: 554

Answers (1)

phiver
phiver

Reputation: 23608

Can't really see why ts(d) |> decompose() doesn't work. I get it to work with fable without any issues. See below.

The package fpp3 contains all the packages you need to work with fable. More info available in Forecasting: principles and practice, 3rd edition.

Note I removed rtools::degrees_to_radians from the example. I don't have access to this function.

library(fpp3)

d = tibble(date = Sys.Date() - 13013:0) |> 
  filter(as.numeric(date) %% 7 == 0) |> 
  mutate(trend = EuStockMarkets[1:n(),1],
         i = as.numeric(date - lubridate::floor_date(date, 'year')),
         cyc = 100 * cos(i),
         noise = 50 * rnorm(n()),
         val = trend + cyc + noise) |> 
  select(date, val)

dcmp <- d %>% 
  tsibble() %>% 
  model(stl = STL(val))

components(dcmp)
# A dable: 1,860 x 7 [7D]
# Key:     .model [1]
# :        val = trend + season_year + remainder
   .model date         val trend season_year remainder season_adjust
   <chr>  <date>     <dbl> <dbl>       <dbl>     <dbl>         <dbl>
 1 stl    1986-10-30 1765. 1641.       24.4       99.4         1740.
 2 stl    1986-11-06 1572. 1640.        4.55     -72.5         1568.
 3 stl    1986-11-13 1601. 1640.       37.7      -77.0         1563.
 4 stl    1986-11-20 1531. 1640.        7.21    -116.          1523.
 5 stl    1986-11-27 1556. 1639.       -7.97     -74.9         1564.
 6 stl    1986-12-04 1610. 1639.        9.21     -38.2         1601.
 7 stl    1986-12-11 1601. 1639.       22.2      -60.1         1578.
 8 stl    1986-12-18 1706. 1638.       15.1       52.8         1691.
 9 stl    1986-12-25 1772. 1638.       11.9      122.          1760.
10 stl    1987-01-01 1802. 1637.       56.5      108.          1746.
# … with 1,850 more rows

# plot
components(dcmp) %>% autoplot()

enter image description here

Upvotes: 1

Related Questions