R's forecast
package bats()
and tbats()
functions can fit BATS and TBATS models to the data. The functions return lists with a class attribute either "bats" or "tbats". One of the elements on this list is a time series of state vectors, $x(t)$, for each time, $t$.
See http://robjhyndman.com/papers/complex-seasonality/ for the formula's and Hyndman et al (2008) for a better description of ETS models. BATS and TBATS are an extension of ETS.
For example:
fit <- bats(myTimeseries)
fit$x
In this case, each row of x
will be on fourier-like harmonic.
There are also plot.tbats()
and plot.bats()
functions to automatically decompose and view the components.
One possibility is to generate the data upon the state-space representation of the basic structural time series model described in Harvey (1989).
Harvey, A. C. (1989)
Forecasting, Structural Time Series Models and the Kalman Filter.
Cambridge University Press.
The basic structural model is defined as follows:
\begin{eqnarray*}
\begin{array}{rll}
\hbox{observed series:} & y_t = \mu_t + \gamma_t + \epsilon_t , &
\epsilon_t \sim \hbox{NID}(0,\, \sigma^2_\epsilon) ; \\
\hbox{latent level:} & \mu_t = \mu_{t-1} + \beta_{t-1} + \xi_t , &
\xi_t \sim \hbox{NID}(0,\, \sigma^2_\xi) ; \\
\hbox{latent drift:} & \beta_t = \beta_{t-1} + \zeta_t , &
\zeta_t \sim \hbox{NID}(0,\, \sigma^2_\zeta) ; \\
\hbox{latent seasonal:} & \gamma_t = \sum_{j=1}^{s-1} -\gamma_{t-j} + \omega_t , &
\omega_t \sim \hbox{NID}(0,\, \sigma^2_\omega) , \\
\end{array}
\end{eqnarray*}
for $t=s,\dots,n$; $s$ is the periodicity of the data
(e.g. $s=4$ for quarterly data).
The model provides a flexible framework to generate the kind of the data you are interested in. Setting $\sigma^2_\omega=0$ yields a model with deterministic seasonality. Setting also $\gamma_1=\dots=\gamma_{s-1}=0$ and $\sigma^2_\zeta=0$ removes the seasonal component and gives the local level model (random walk plus noise model with drift $\beta_0$). If $\sigma^2_\zeta > 0$ the local trend model is obtained, where the drift follows a random walk.
The function datagen.stsm
in package stsm generates data from this model. For example, the data employed in some of the simulation exercises used to test package are generated as follows:
# generate a quarterly series from a local level plus seasonal model
require(stsm)
pars <- c(var1 = 300, var2 = 10, var3 = 100)
m <- stsm.model(model = "llm+seas", y = ts(seq(120), frequency = 4),
pars = pars, nopars = NULL,)
ss <- char2numeric(m)
set.seed(123)
y <- datagen.stsm(n = 120, model = list(Z = ss$Z, T = ss$T, H = ss$H, Q = ss$Q),
n0 = 20, freq = 4, old.version = TRUE)$data
plot(y, main = "data generated from the local-level plus seasonal component")
Best Answer
What you are driving at here is unclear to me, but there is a simple answer to your postulate. If there is no seasonal variation, there is nothing to "remove" and methods designed to identify seasonal components should find nothing (or, in practice, produce additive estimates near zero or multiplicative estimates near one). That's pretty much a tautology. Benignly put, fitting some decomposition with a seasonal component should do no harm if that component is negligible.
As you are asking about seasonality in general, I'd warn against the disciplinary myopia that often affects discussions in this field. In particular, many economists are focused on the idea that seasonality is irrelevant or a nuisance and so must be removed. That may well be true depending on their goal. More positively, environmental scientists and epidemiologists of various kinds often regard seasonality as interesting or important. (These named communities are naturally not the only groups concerned with seasonality.)
In terms of your initial question -- How do you know when deseasonalization is not necessary? -- I'd say that if seasonality is important, you can spot it on a graph, but plot against time of year as well as time. In practice, with strongly trending series, detrending first, even crudely, can help. As always, there are many statistical people who prefer a formal test.