library(cmdstanr)
library(ggplot2)
library(tidyverse)
library(tidybayes)
library(targets)
tar_load(one_time)
plot(one_time, type = "l")
Controversy!
# load the model in stan
<- cmdstan_model(here::here("posts/2023-11-24-how-to-model-growth/ar1.stan"))
transition
transition
data{
int n;
vector[n] time;
vector[n] x;
}// transformed data {
// vector[n] x = log(pop);
// }
parameters {
real<lower=0> a;
real<lower=0,upper=1> b;
real<lower=0> sigma;
}transformed parameters {
real mu_max = a / (1 - b);
real sigma_max = sigma /sqrt(1 - b^2);
}model {
2, .5);
a ~ normal(5,2);
b ~ beta(5);
sigma ~ exponential(
x ~ normal(1 - pow(b, time)),
mu_max .* (1 - pow(b^2, time))
sigma_max .* sqrt(
);
}generated quantities {
vector[15] x_pred;
1] = 0;
x_pred[for (j in 1:14) {
1] = normal_rng(
x_pred[j+1 - pow(b, j)),
mu_max * (1 - pow(b^2, j))
sigma_max * sqrt(
);
} }
Here is another approach, using a lagged population growth model
# load the model in stan
<- cmdstan_model(here::here("posts/2023-11-24-how-to-model-growth/multiple_spp_ar1.stan"))
lagged_growth
lagged_growth
data {
int n;
int nclone;
vector[n] x;
array[n] int<lower=1, upper=nclone> clone_id;
// for predictions
int<lower=0, upper=1> fit;
int nyear;
}
transformed data {
array[n - nclone] int time;
array[n - nclone] int time_m1;
for (i in 2:n) {
if (clone_id[i] == clone_id[i-1]) {
time[i - clone_id[i]] = i;
time_m1[i - clone_id[i]] = i - 1;
}
}
}
parameters {
real<lower=0> a;
real<lower=0,upper=1> b;
real<lower=0> sigma;
}
model {
a ~ normal(2, .5);
b ~ beta(5,2);
sigma ~ exponential(5);
if (fit == 1) {
x[time] ~ normal(
a + b * x[time_m1],
sigma);
}
}
generated quantities {
vector[nyear] x_pred;
x_pred[1] = 0;
for (j in 2:nyear){
x_pred[j] = a + b * x_pred[j-1] + normal_rng(0, sigma);
}
}
Simulations
Here are simulations from a one-species AR-1 model that imitate Ives et al. figure 1.
<- function(
simulate_pop_growth a = 0,
b, sigma = 1,
tmax = 50,
x0 = -8) {
<- numeric(tmax)
xvec
1] <- x0
xvec[
## process error
<- rnorm(tmax, mean = 0, sd = sigma)
eta
for(time in 2:tmax){
<- a + b*xvec[time-1] + eta[time]
xvec[time]
}
return(xvec)
}
I’m going to simulate a modest number of time series, and choose parameters to make the time series slightly resemble the aphid experiment.
= 1
a_fig = .8
b_fig = .7
sigma_fig
<- map_dfr(1:12,
ts_data ~ tibble(
pop = simulate_pop_growth(
a = a_fig,
b = b_fig,
tmax = 16,
sigma = sigma_fig,
x0 = 0
),time = 0:(length(pop)-1)
),.id = "sim"
)
|>
ts_data ggplot(aes(x =time, y = pop, group = sim)) +
geom_line()
::kable(head(ts_data)) knitr
sim | pop | time |
---|---|---|
1 | 0.0000000 | 0 |
1 | 0.9548568 | 1 |
1 | 2.8629644 | 2 |
1 | 2.8740721 | 3 |
1 | 2.5695696 | 4 |
1 | 3.2455612 | 5 |
Transition distribution
<- filter(ts_data, time != 0)
ts_data_nozero
<- transition$sample(
transition_sample data = list(n = nrow(ts_data_nozero),
x = ts_data_nozero$pop,
time = ts_data_nozero$time),
parallel_chains = 4, refresh = 0)
Running MCMC with 4 parallel chains...
Chain 1 finished in 1.7 seconds.
Chain 3 finished in 1.7 seconds.
Chain 2 finished in 1.8 seconds.
Chain 4 finished in 1.7 seconds.
All 4 chains finished successfully.
Mean chain execution time: 1.7 seconds.
Total execution time: 2.0 seconds.
|>
transition_sample spread_rvars(x_pred[time]) |>
ggplot(aes(x = time-1, ydist = x_pred)) +
stat_lineribbon() +
scale_fill_brewer(palette = "Greens", direction = -1) +
theme_bw() +
geom_line(aes(x = time, y = pop, group = sim),
inherit.aes = FALSE, data = ts_data) +
labs(x = "Time", y = "log population size")
|>
transition_sample gather_rvars(a, b, sigma) |>
ggplot(aes(y = .variable, dist = .value)) +
stat_halfeye() +
geom_point(
aes(y = .variable, x = .value),
inherit.aes = FALSE,
data = tribble(
~ .variable, ~.value,
"a", a_fig,
"b", b_fig,
"sigma", sigma_fig), col = "red", size = 2)
Lagged model
This time there is no need to drop 0s
<- ts_data |>
ts_data mutate(sim = readr::parse_number(sim))
<- lagged_growth$sample(
lagged_growth_sample data = list(n = nrow(ts_data),
nclone = max(ts_data$sim),
x = ts_data$pop,
time = ts_data$time,
clone_id = ts_data$sim,
fit = 1,
nyear = 15),
parallel_chains = 4, refresh = 0)
Running MCMC with 4 parallel chains...
Chain 1 finished in 0.3 seconds.
Chain 2 finished in 0.3 seconds.
Chain 3 finished in 0.3 seconds.
Chain 4 finished in 0.3 seconds.
All 4 chains finished successfully.
Mean chain execution time: 0.3 seconds.
Total execution time: 0.5 seconds.
predictions
|>
lagged_growth_sample spread_rvars(x_pred[time]) |>
ggplot(aes(x = time-1, ydist = x_pred)) +
stat_lineribbon() +
scale_fill_brewer(palette = "Greens", direction = -1) +
theme_bw() +
geom_line(aes(x = time, y = pop, group = sim),
inherit.aes = FALSE, data = ts_data) +
labs(x = "Time", y = "log population size")
parameters
|>
lagged_growth_sample gather_rvars(a, b, sigma) |>
ggplot(aes(y = .variable, dist = .value)) +
stat_halfeye() +
geom_point(
aes(y = .variable, x = .value),
inherit.aes = FALSE,
data = tribble(
~ .variable, ~.value,
"a", a_fig,
"b", b_fig,
"sigma", sigma_fig), col = "red", size = 2)