Abyssal Beauty
Abyssal Beauty

Reputation: 27

Decomposing a zoo object without the periodic error

I'm trying to decompose a daily time series into the seasonal, trend, and remainder part. We can look at an example with google stocks provided by the fpp2 package :

Loading libraries

library(forecast)
library(lubridate) 
library(zoo)
library(fpp2)

Transform the time series of the package into a numeric vector

google <- as.numeric(goog)

Based on the documentation, google stocks go from 2013-02-25 to 2017-02-23

googZ <- zoo(google, seq(from = as.Date("2013-02-25"), to = as.Date("2017-02-23"), by = "days"))

Error in decompose(googZ) : time series has no or less than 2 periods

decompose(googZ)

Error in decompose(googZ) : time series has no or less than 2 periods

This one works however and I'm not sure why the Google on is not

autoplot(decompose(AirPassengers))
str(AirPassengers)

I don't understand why is this happening as we clearly have and defined correctly our time series. Note that I used the zoo package because ts can't handle daily time series. Thank you very much !

Upvotes: 0

Views: 1305

Answers (1)

G. Grothendieck
G. Grothendieck

Reputation: 269654

decompose requires

  • a regularly spaced ts series
  • the same number of points per period, e.g. 365 points per year assuming year is one period
  • that the period be 1
  • that the points within a period be deltat apart where delatt = 1/frequency and frequency is the number of points per period

Date class objects are represented as days since the Epoch (Jan 1, 1970). Due to leap years Date objects do not have the same number of points per year, the difference between successive years is 365 or 366, not 1, and the points are 1 apart, not deltat apart.

What we can do to force fit it into a ts object is to take the first 365 days per year (on leap years this will drop Dec 31) and then use this. Note that the year component of POSIXlt objects is the number of years since 1900 so we must add the 1900 back and the yday component is 0 for Jan 1st, 1 for Jan 2nd and so on to 364 for a non-leap year and 365 for a leap year.

library(ggplot2)
library(zoo)

lt <- as.POSIXlt(time(goog2))
tt <- with(lt, ts(coredata(goog2[yday < 365]), 
  start = year[1] + 1900 + yday[1]/365, frequency = 365))
autoplot(decompose(tt))

giving:

screenshot

Upvotes: 3

Related Questions