The {MARSS} package fits multivariate autoregressive state-space (MARSS) models and the {marssTMB} is a companion package that allows fast model fitting via TMB. MARSS models take the form: c and d are inputs (aka, exogenous variables or covariates or indicator variables) and must have no missing values. They are not treated as `data’ in the likelihood but as inputs.
Example: a mean-reverting random walk model with three observation time series:
To fit a MARSS model with the {MARSS} package, we translate the mathematical model written in matrix form into equivalent matrices (or arrays if time-varying) in code. Matrices that combine fixed and estimated values are specified using a list matrix with numerical values for fixed values and character names for the estimated values.
The model above is written as
B1 <- matrix(list("b",0,0,"b"),2,2)
U1 <- matrix(0,2,1)
Q1 <- matrix(c("q11","q12","q12","q22"),2,2)
Z1 <- matrix(c(1,0,1,1,1,0),3,2)
A1 <- matrix(list("a1",0,0),3,1)
R1 <- matrix(list("r11",0,0,0,"r",0,0,0,"r"),3,3)
pi1 <- matrix(0,2,1); V1=diag(1,2)
model.list <- list(B=B1,U=U1,Q=Q1,Z=Z1,A=A1,R=R1,x0=pi1,V0=V1,tinitx=0)
Notice the one-to-one correspondence between the model in and the
math version of the model. The matrix names in the model list must be B,
U, Q, Z, A, R, x0, V0. The tinitx
element tells MARSS
whether the initial state for x is at t = 1 (tinitx=1
) or
t = 0 (tinitx=0
).
The data must be entered as a n × T matrix, or a ts
object or vector (which will be converted to a n × T matrix). MARSS has a
number of text shortcuts for common parameter forms, such as ``diagonal
and unequal’’; see the User Guide for the possible shortcuts. You can
leave off matrix names and the defaults will be used. See
[MARSS::MARSS.marxss()] for the defaults.
Harbor seal counts:
Fit but set B to identity.
library(marssTMB)
model.list$B <- diag(1,2)
fit <- MARSS(dat, model=model.list, method="TMB")
#>
#> MARSS fit is
#> Estimation method: TMB
#> WARNING: nlminb() ran for 43 iterations and stopped before maxit with a convergence warning.
#> Treat the parameter values and logLik with caution. Message: false convergence (8) .
#> Log-likelihood: -48.02187
#> AIC: 108.0437 AICc: 109.8698
#>
#> Estimate
#> A.a1 -8.25e+00
#> R.r11 1.08e-13
#> R.r 3.87e-02
#> Q.q11 6.69e-03
#> Q.q12 1.84e-02
#> Q.q22 5.03e-02
#> Initial states (x0) defined at t=0
#>
#> Standard errors have not been calculated.
#> Use MARSSparamCIs to compute CIs and bias estimates.
The R, Q and Λ variances can be set to zero to specify partially deterministic systems. This allows you to write MAR(p) models in MARSS form for example. See the User Guide for examples.
The main function is which returns a vector of only the estimated parameters.
coef(fit, type="vector")
#> A.a1 R.r11 R.r Q.q11 Q.q12
#> -8.245232e+00 1.080165e-13 3.871942e-02 6.692311e-03 1.835152e-02
#> Q.q22
#> 5.033113e-02
You can include type="matrix"
to the full parameter
matrices.
You can get a pretty version of the estimates with SEs and CIs with
tidy(fit)
#> term estimate std.error conf.low conf.up
#> 1 A.a1 -8.245232e+00 0.066518452 -8.375605782 -8.11485824
#> 2 R.r11 1.080165e-13 0.009034089 -0.017706489 0.01770649
#> 3 R.r 3.871942e-02 0.010586436 0.017970386 0.05946845
#> 4 Q.q11 6.692311e-03 0.005133034 -0.003368251 0.01675287
#> 5 Q.q12 1.835152e-02 0.007851843 0.002962192 0.03374085
#> 6 Q.q22 5.033113e-02 0.022125760 0.006965435 0.09369682
To get the estimated states (the expected value), use
tsSmooth(fit) |> head()
#> .rownames t .estimate .se
#> 1 X1 1 7.148407 0.03330101
#> 2 X1 2 7.188503 0.08038564
#> 3 X1 3 7.228598 0.09559314
#> 4 X1 4 7.268693 0.09559052
#> 5 X1 5 7.308788 0.08037630
#> 6 X1 6 7.348883 0.03326342
If you want a matrix of the states, you can use
fit$states
.
The fitted values are the model estimates for the data.
Use ggplot2::autoplot()
for a print out of various
standard diagnostic plots.
Use [MARSS::residuals()] for the residuals.
residuals(fit) |> head()
#> type .rownames name t value .fitted .resids .sigma .std.resids
#> 1 ytt1 SJF model 1 6.033086 -8.245232 14.278318 1.4469715 9.867726
#> 2 ytt1 SJF model 2 NA 6.033086 NA NA NA
#> 3 ytt1 SJF model 3 NA 6.033086 NA NA NA
#> 4 ytt1 SJF model 4 NA 6.033086 NA NA NA
#> 5 ytt1 SJF model 5 NA 6.033086 NA NA NA
#> 6 ytt1 SJF model 6 6.783325 6.033086 0.750239 0.6845673 1.095932
To produce predictions and forecasts from a MARSS model, see [MARSS::predict()] or [MARSS::forecast()]
forecast(fit)$pred |> head()
#> .rownames t y estimate se Lo 80 Hi 80 Lo 95
#> 1 SJF 1 6.033086 6.033086 4.643034e-07 6.033086 6.033087 6.033085
#> 2 SJF 2 NA 6.183134 2.738269e-01 5.832211 6.534057 5.646443
#> 3 SJF 3 NA 6.333182 3.353681e-01 5.903390 6.762973 5.675872
#> 4 SJF 4 NA 6.483230 3.353681e-01 6.053438 6.913021 5.825920
#> 5 SJF 5 NA 6.633277 2.738269e-01 6.282354 6.984201 6.096586
#> 6 SJF 6 6.783325 6.783325 4.648522e-07 6.783325 6.783326 6.783324
#> Hi 95
#> 1 6.033087
#> 2 6.719825
#> 3 6.990491
#> 4 7.140539
#> 5 7.169968
#> 6 6.783326
[MARSS::toLatex.marssMLE()] allows you to create LaTeX for your model that you can include in your files.
Specification of a properly constrained model with a unique solution is the responsibility of the user because the {MARSS} package has no way to tell if you have specified an insufficiently constrained model.
Use [MARSS::autoplot()] to see a series of standard plots and
diagnostics for your model. Try [MARSS::MARSSinfo()] if you get errors
you don’t understand or fitting is taking a long time to converge. Use
fit=FALSE
in your [MARSS()] call to set up a model without
fitting. Let’s say you do fit <- MARSS(..., fit=FALSE)
.
Now you can do summary(fit$model)
to see what [MARSS()]
thinks you are trying to fit.
Let’s say you specified your model with some text short-cuts, like
Q="unconstrained"
, but you want the list matrix form for a
next step. a <- summary(fit$model)
returns that list
(invisibly). Because the model argument of MARSS()
will
understand a list of list matrices, you can pass in model=a
to specify the model.
MARSSkfas(fit, return.kfas.model=TRUE)
will return your
model in {KFAS} format (class SSModel), thus you can use all the
functions available in the {KFAS} package on your model.
Not provided with {marssTMB}. See the {MARSS} package instead.
Not currently implemented in {marssTMB}. Use the {MARSS} package for time-varying parameters.
Lectures and more examples on fitting multivariate models can be found at our course website [https://atsa-es.github.io/atsa] and course eBook [https://atsa-es.github.io/atsa-labs].
The MARSS User Guide starts with some tutorials on MARSS models and walks through many examples showing how to write multivariate time-series models in MARSS form. The User Guide also has vignettes: how to write AR(p) models in state-space form, dynamic linear models (regression models where the regression parameters are AR(p)), multivariate regression models with regression parameters that are time-varying and enter the non-AR part of your model or the AR part, detecting breakpoints using state-space models, and dynamic factor analysis. All of these can be written in MARSS form. It also has a series of vignettes on analysis of multivariate biological data.