You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We can also model the intercept as a random walk by removing the intercept from the main formula (adding `0` to the model equation) and including the argument `time_varying = ~1`:
density ~ s(year, k = 5) + depth_scaled + depth_scaled2, #<< add smoother on year
154
154
time = "year",
@@ -174,42 +174,60 @@ In deciding which method (AR(1), RW, etc) to use for including time in the model
174
174
# `project()`` function for faster long-term forecasting
175
175
176
176
Because forecasting can be slow---especially for large datasets or for projections far into the future, sdmTMB also includes a `project()` function for doing projections via simulations.
177
-
Keeping with the `pcod` dataset, we'll first define the years for the historical (fitting) and projection period.
177
+
Using the built-in `dogfish` dataset, we'll first define the years for the historical (fitting) and projection period. This is based off an approach first developed in the `project_model()` function in VAST.
Next, we'll fit the model. This is a binomial model of presence-absence, with no covariates and an AR(1) spatiotemporal field that is responsible for future forecasts.
188
+
189
+
Next, we'll fit the model. We'll use an AR(1) spatiotemporal field that is responsible for future forecasts.
188
190
189
191
```{r}
190
192
fit <- sdmTMB(
191
-
present ~ 1,
193
+
catch_weight ~ 1,
192
194
time = "year",
195
+
offset = log(dogfish$area_swept),
193
196
extra_time = historical_years, #< does *not* include projection years
194
197
spatial = "on",
195
198
spatiotemporal = "ar1",
196
-
data = pcod,
199
+
data = dogfish,
197
200
mesh = mesh,
198
-
family = binomial()
201
+
family = tweedie(link = "log")
199
202
)
200
203
```
201
204
202
-
Finally, we'll do the projections for the last 5 years.
203
-
We'll only use 20 draws for simplicity, but you should increase this for real-world applications so that you have stable results.
205
+
Finally, we'll do the projections.
206
+
We'll only use 20 draws for speed and simplicity, but you should increase this for real-world applications so that you have stable results.
204
207
205
-
```{r}
208
+
```{r, message=FALSE}
206
209
set.seed(1)
207
210
out <- project(fit, newdata = proj_grid, nsim = 20)
208
211
```
209
212
210
-
The `out` object now contains two objects: `out$est` and `out$epsilon_est`, each with dimensions of the number of rows in the prediction data (`proj_grid`) and number of draws for this example (n = 20).
213
+
The `out` object now contains two objects: `out$est` and `out$epsilon_est`, each with dimensions of the number of rows in the prediction data (`proj_grid`) (rows) and number of draws for this example (n = 20) (columns).
214
+
The first (`est`) are the predictions (in link space) and the second (`epsilon_est`) is the spatiotemporal random effects.
211
215
These can be summarized and visualized in several ways to show trends in both the mean, as well as the confidence intervals.
212
216
217
+
For example, here are the projections:
218
+
219
+
```{r}
220
+
proj_grid$est_mean <- apply(out$est, 1, mean)
221
+
ggplot(subset(proj_grid, year > 2022), aes(X, Y, fill = est_mean)) +
222
+
geom_raster() +
223
+
facet_wrap(~year) +
224
+
coord_fixed() +
225
+
scale_fill_viridis_c() +
226
+
ggtitle("Projection simulation (mean)")
227
+
```
228
+
229
+
See the help file `?sdmTMB::project` for additional examples.
230
+
213
231
# Interpolating in space to unsampled areas
214
232
215
233
We can also interpolate predicted values to unsampled areas within the geographic extent of the data.
@@ -275,36 +293,38 @@ newdf <- expand.grid(
275
293
x = seq(min(dat$x), max(dat$x), 5),
276
294
y = seq(min(dat$y), max(dat$y), 5)
277
295
)
278
-
p <- predict(fit,
279
-
newdata = newdf, se_fit = TRUE
280
-
)
296
+
p <- predict(fit, newdata = newdf)
281
297
282
298
ggplot(p, aes(x, y)) +
283
299
geom_raster(data = p, aes(x, y, fill = est)) +
284
300
geom_point(data = dat, aes(x, y)) +
285
-
labs(fill = "tree density")
301
+
labs(fill = "tree density") +
302
+
scale_fill_viridis_c()
286
303
```
287
304
288
-
We can also use add the argument `nsim = 500` when predicting and then summarize predicted densities from all simulations in a matrix
305
+
We can also use add the argument `nsim = 200` when predicting and then summarize predicted densities from all simulations in a matrix
289
306
290
307
```{r}
291
-
p2 <- predict(fit, newdata = newdf, nsim = 500)
308
+
p2 <- predict(fit, newdata = newdf, nsim = 200)
292
309
newdf$p2 <- apply(p2, 1, mean)
293
310
ggplot(newdf, aes(x, y)) +
294
311
geom_raster(data = newdf, aes(x, y, fill = p2)) +
295
312
geom_point(data = dat, aes(x, y)) +
296
-
labs(fill = "tree density")
313
+
labs(fill = "tree density") +
314
+
scale_fill_viridis_c()
297
315
```
298
316
299
317
We can also visualize uncertainty in the forecasts by mapping the standard error of predicted densities at each point in space.
300
318
We see that uncertainty is higher at vertices.
301
319
This is because there are fewer neighbors, e.g. [this tutorial](https://ourcodingclub.github.io/tutorials/spatial-modelling-inla/)
302
320
303
321
```{r vis-vert}
322
+
newdf$est_se <- apply(p2, 1, sd)
304
323
ggplot() +
305
-
geom_point(data = p, aes(x = x, y = y, col = est_se)) +
324
+
geom_raster(data = newdf, aes(x = x, y = y, fill = est_se)) +
0 commit comments