tinyVAST
includes features to fit a dynamic structural
equation model. We here show this using a bivariate vector
autoregressive model for wolf and moose abundance on Isle Royale.
data(isle_royale, package="dsem")
# Convert to long-form
data = expand.grid( "time"=isle_royale[,1], "var"=colnames(isle_royale[,2:3]) )
data$logn = unlist(log(isle_royale[2:3]))
# Define cross-lagged DSEM
dsem = "
# Link, lag, param_name
wolves -> wolves, 1, arW
moose -> wolves, 1, MtoW
wolves -> moose, 1, WtoM
moose -> moose, 1, arM
#wolves -> moose, 0, corr
wolves <-> moose, 0, corr
"
# fit model
mytiny = tinyVAST( dsem = dsem,
data = data,
times = isle_royale[,1],
variables = colnames(isle_royale[,2:3]),
formula = logn ~ 0 + var )
mytiny
#> Call:
#> tinyVAST(formula = logn ~ 0 + var, data = data, dsem = dsem,
#> times = isle_royale[, 1], variables = colnames(isle_royale[,
#> 2:3]))
#>
#> Run time:
#> Time difference of 0.6740656 secs
#>
#> Family:
#> $obs
#>
#> Family: gaussian
#> Link function: identity
#>
#>
#>
#>
#> sdreport(.) result
#> Estimate Std. Error
#> alpha_j 3.32526197 2.483494e-01
#> alpha_j 6.44165343 2.116035e-01
#> beta_z 0.89304266 8.420632e-02
#> beta_z 0.01420908 1.279150e-01
#> beta_z -0.13239996 3.454997e-02
#> beta_z 0.86147627 7.107386e-02
#> beta_z -0.01285890 5.063467e-02
#> beta_z 0.37727131 3.504314e-02
#> beta_z 0.17062266 1.584742e-02
#> log_sigma -12.62531823 2.008272e+04
#> Maximum gradient component: 3.635293e-05
#>
#> Proportion conditional deviance explained:
#> [1] 1
#>
#> DSEM terms:
#> heads to from parameter start lag Estimate Std_Error z_value
#> 1 1 wolves wolves 1 <NA> 1 0.89304266 0.08420632 10.6054118
#> 2 1 wolves moose 2 <NA> 1 0.01420908 0.12791496 0.1110823
#> 3 1 moose wolves 3 <NA> 1 -0.13239996 0.03454997 -3.8321293
#> 4 1 moose moose 4 <NA> 1 0.86147627 0.07107386 12.1208601
#> 5 2 moose wolves 5 <NA> 0 -0.01285890 0.05063467 -0.2539545
#> 6 2 wolves wolves 6 <NA> 0 0.37727131 0.03504314 10.7659099
#> 7 2 moose moose 7 <NA> 0 0.17062266 0.01584742 10.7665881
#> p_value
#> 1 2.812224e-26
#> 2 9.115511e-01
#> 3 1.270389e-04
#> 4 8.189516e-34
#> 5 7.995307e-01
#> 6 4.986648e-27
#> 7 4.950067e-27
#>
#> Fixed terms:
#> Estimate Std_Error z_value p_value
#> varwolves 3.325262 0.2483494 13.38945 6.969636e-41
#> varmoose 6.441653 0.2116035 30.44210 1.524035e-203
# Deviance explained relative to both intercepts
# Note that a process-error-only estimate with have devexpl -> 1
deviance_explained( mytiny,
null_formula = logn ~ 0 + var )
#> [1] 1
heads | to | from | parameter | start | lag | Estimate | Std_Error | z_value | p_value |
---|---|---|---|---|---|---|---|---|---|
1 | wolves | wolves | 1 | NA | 1 | 0.893 | 0.084 | 10.605 | 0.000 |
1 | wolves | moose | 2 | NA | 1 | 0.014 | 0.128 | 0.111 | 0.912 |
1 | moose | wolves | 3 | NA | 1 | -0.132 | 0.035 | -3.832 | 0.000 |
1 | moose | moose | 4 | NA | 1 | 0.861 | 0.071 | 12.121 | 0.000 |
2 | moose | wolves | 5 | NA | 0 | -0.013 | 0.051 | -0.254 | 0.800 |
2 | wolves | wolves | 6 | NA | 0 | 0.377 | 0.035 | 10.766 | 0.000 |
2 | moose | moose | 7 | NA | 0 | 0.171 | 0.016 | 10.767 | 0.000 |
And we can specifically inspect the estimated interaction matrix:
wolves | moose | |
---|---|---|
wolves | 0.893 | -0.132 |
moose | 0.014 | 0.861 |
We can then compare this with package dsem
library(dsem)
# Keep in wide-form
dsem_data = ts( log(isle_royale[,2:3]), start=1959)
family = c("normal","normal")
# fit without delta0
# SEs aren't available because measurement errors goes to zero
mydsem = dsem::dsem( sem = dsem,
tsdata = dsem_data,
control = dsem_control(getsd=FALSE),
family = family )
#> 1 regions found.
#> Using 1 threads
#> 1 regions found.
#> Using 1 threads
#> Coefficient_name Number_of_coefficients Type
#> 1 beta_z 7 Fixed
#> 2 lnsigma_j 2 Fixed
#> 3 mu_j 2 Random
#> 4 x_tj 122 Random
mydsem
#> $par
#> beta_z beta_z beta_z beta_z beta_z
#> 0.895834720 0.007358847 -0.124879928 0.874884847 -0.014394603
#> beta_z beta_z lnsigma_j lnsigma_j
#> 0.378522244 0.172997994 -16.141398482 -12.488408401
#>
#> $objective
#> [1] 7.739638
#> attr(,"logarithm")
#> [1] TRUE
#>
#> $convergence
#> [1] 0
#>
#> $iterations
#> [1] 76
#>
#> $evaluations
#> function gradient
#> 99 77
#>
#> $message
#> [1] "relative convergence (4)"
path | lag | name | start | parameter | first | second | direction | Estimate |
---|---|---|---|---|---|---|---|---|
wolves -> wolves | 1 | arW | NA | 1 | wolves | wolves | 1 | 0.896 |
moose -> wolves | 1 | MtoW | NA | 2 | moose | wolves | 1 | 0.007 |
wolves -> moose | 1 | WtoM | NA | 3 | wolves | moose | 1 | -0.125 |
moose -> moose | 1 | arM | NA | 4 | moose | moose | 1 | 0.875 |
wolves <-> moose | 0 | corr | NA | 5 | wolves | moose | 2 | -0.014 |
wolves <-> wolves | 0 | V[wolves] | NA | 6 | wolves | wolves | 2 | 0.379 |
moose <-> moose | 0 | V[moose] | NA | 7 | moose | moose | 2 | 0.173 |
where we again inspect the estimated interaction matrix:
wolves | moose | |
---|---|---|
wolves | 0.896 | -0.125 |
moose | 0.007 | 0.875 |