15.3 Using DLMs to estimate changing season
Here is a DLM model with the level and season modeled as a random walk.
\[\begin{bmatrix}x \\ \beta_1 \\ \beta_2 \end{bmatrix}_t = \begin{bmatrix}x \\ \beta_1 \\ \beta_2 \end{bmatrix}_{t-1} + \begin{bmatrix}w_1 \\ w_2 \\ w_3 \end{bmatrix}_t\] \[y_t = \begin{bmatrix}1& \sin(2\pi t/p)&\cos(2\pi t/p)\end{bmatrix} \begin{bmatrix}x \\ \beta_1 \\ \beta_2 \end{bmatrix}_t + v_t\]
We can fit the model to the \(y_t\) data and estimate the \(\beta\)’s and \(\alpha\). We specify this one-to-one in R for MARSS()
.
Z
is time-varying and we set this up with an array with the 3rd dimension being time.
<- array(1, dim = c(1, 3, TT))
Z 1, 2, ] <- sin(2 * pi * (1:TT)/12)
Z[1, 3, ] <- cos(2 * pi * (1:TT)/12) Z[
Then we make our model list. We need to set A
since MARSS()
doesn’t like the default value of scaling
when Z
is time-varying.
<- list(U = "zero", Q = "diagonal and unequal", Z = Z,
mod.list A = "zero")
When we fit the model we need to give MARSS()
initial values for x0
. It cannot come up with default ones for this model. It doesn’t really matter what you pick.
require(MARSS)
<- MARSS(yt, model = mod.list, inits = list(x0 = matrix(0,
fit 3, 1)))
Success! abstol and log-log tests passed at 45 iterations.
Alert: conv.test.slope.tol is 0.5.
Test with smaller values (<0.1) to ensure convergence.
MARSS fit is
Estimation method: kem
Convergence test: conv.test.slope.tol = 0.5, abstol = 0.001
Estimation converged in 45 iterations.
Log-likelihood: 19.0091
AIC: -24.01821 AICc: -22.80082
Estimate
R.R 0.00469
Q.(X1,X1) 0.01476
Q.(X2,X2) 0.00638
Q.(X3,X3) 0.00580
x0.X1 -0.11002
x0.X2 -0.85340
x0.X3 0.92787
Initial states (x0) defined at t=0
Standard errors have not been calculated.
Use MARSSparamCIs to compute CIs and bias estimates.
The \(\beta_1\) estimate is State X2 and \(\beta_2\) is State X3. The estimates match what we put into the simulated data.
plot type = "xtT" Estimated states
We can compare the estimated cycles to the ones used in the simulation.
We can make this a bit harder by imagining that our data have missing values. Let’s imagine that we only observe half the months.
<- yt
yt.miss sample(100, 50)] <- NA
yt.miss[plot(yt, type = "l")
points(yt.miss)
require(MARSS)
<- MARSS(yt.miss, model = mod.list, inits = list(x0 = matrix(0,
fit.miss 3, 1)))
Success! abstol and log-log tests passed at 108 iterations.
Alert: conv.test.slope.tol is 0.5.
Test with smaller values (<0.1) to ensure convergence.
MARSS fit is
Estimation method: kem
Convergence test: conv.test.slope.tol = 0.5, abstol = 0.001
Estimation converged in 108 iterations.
Log-likelihood: 0.1948933
AIC: 13.61021 AICc: 16.27688
Estimate
R.R 0.00243
Q.(X1,X1) 0.01342
Q.(X2,X2) 0.00794
Q.(X3,X3) 0.00580
x0.X1 -0.11497
x0.X2 -0.82921
x0.X3 0.92696
Initial states (x0) defined at t=0
Standard errors have not been calculated.
Use MARSSparamCIs to compute CIs and bias estimates.
The model still can pick out the changing seasonal cycle.
plot type = "xtT" Estimated states