16.3 Modeling the cycle
As discussed in Chapter 15 in the covariates chapter, we can model changes in seasonality with a DLM with sine and cosine covariates. 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 Kvichak River log spawner data and estimate the \(\beta\)’s and stochastic level (\(x\)). This is annual data so what does \(p\) mean? \(p\) is the time steps between peaks. For sockeye that is 5 years. So we set \(p=5\). If \(p\) were changing, that would cause problems, but it is not for these data (which you can confirm by looking at the ACF for different parts of the time series).
16.3.1 Set up the data
<- "KVICHAK"
river <- subset(sockeye, region == river)
df <- log(df$spawners)
yt <- length(yt)
TT <- 5 p
16.3.2 Specify the \(\mathbf{Z}\) matrix
\(\mathbf{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)/p)
Z[1, 3, ] <- cos(2 * pi * (1:TT)/p) Z[
16.3.3 Specify the model list
Then we make our model list. We need to set \(\mathbf{A}\) since MARSS()
doesn’t like the default value of scaling
when \(\mathbf{Z}\) is time-varying.
<- list(U = "zero", Q = "diagonal and unequal", Z = Z,
mod.list A = "zero")
16.3.4 Fit the model
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.
<- dim(Z)[2]
m <- MARSS(yt, model = mod.list, inits = list(x0 = matrix(0,
fit 1))) m,
Warning! Abstol convergence only. Maxit (=500) reached before log-log convergence.
MARSS fit is
Estimation method: kem
Convergence test: conv.test.slope.tol = 0.5, abstol = 0.001
WARNING: Abstol convergence only no log-log convergence.
maxit (=500) reached before log-log convergence.
The likelihood and params might not be at the ML values.
Try setting control$maxit higher.
Log-likelihood: -58.61614
AIC: 131.2323 AICc: 133.899
Estimate
R.R 0.415426
Q.(X1,X1) 0.012584
Q.(X2,X2) 0.000547
Q.(X3,X3) 0.037008
x0.X1 7.897380
x0.X2 -0.855359
x0.X3 1.300854
Initial states (x0) defined at t=0
Standard errors have not been calculated.
Use MARSSparamCIs to compute CIs and bias estimates.
Convergence warnings
Warning: the Q.(X2,X2) parameter value has not converged.
Type MARSSinfo("convergence") for more info on this warning.
16.3.5 Plot the output
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 plot our cycle estimates and see that the peak has shifted over time. The peak has not been regularly every 5 years.
Let’s look at the other rivers. Write a function to do the fit.
<- function(river, p = 5) {
fitriver <- subset(sockeye, region == river)
df <- log(df$spawners)
yt <- length(yt)
TT <- array(1, dim = c(1, 3, TT))
Z 1, 2, ] <- sin(2 * pi * (1:TT)/p)
Z[1, 3, ] <- cos(2 * pi * (1:TT)/p)
Z[<- list(U = "zero", Q = "diagonal and unequal",
mod.list Z = Z, A = "zero")
<- MARSS(yt, model = mod.list, inits = list(x0 = matrix(0,
fit 3, 1)), silent = TRUE)
return(fit)
}
The make a list with all the fits.
<- list()
fits for (river in names(a)) {
<- fitriver(river)
fits[[river]] }
Create a data frame of the amplitude of the cycle (\(\sqrt{\beta_1^2+\beta_2^2}\)) and the stochastic level (\(x\)).
<- data.frame()
dfz for (river in names(a)) {
<- fits[[river]]
fit <- data.frame(amplitude = sqrt(fit$states[2, ]^2 + fit$states[3,
tmp ^2), trend = fit$states[1, ], river = river, brood_year = subset(sockeye,
]== river)$brood_year)
region <- rbind(dfz, tmp)
dfz }