Skip to contents

Specify a first-order random walk temporal random effect. RW1 assumes that the difference between consecutive time points is normally distributed: phi[t] - phi[t-1] ~ N(0, sigma^2).

This is an intrinsic model (improper prior) that captures smooth temporal trends. It is equivalent to an ICAR model on a 1D chain.

Usage

temporal_rw1(time_var, group_var = NULL, cyclic = FALSE, shared = TRUE)

Arguments

time_var

Name of the time variable in data. Can be a formula (e.g., ~ year) or a character string (e.g., "year").

group_var

Optional name of grouping variable for panel data. If provided, separate random walks are estimated for each group.

cyclic

Logical; if TRUE, the random walk wraps around (first and last time points are neighbors). Useful for seasonal data.

shared

Logical; if TRUE (default), temporal effect enters both numerator and denominator linear predictors identically.

Value

A ratiod_temporal object

Details

The RW1 precision matrix Q has the form (for T time points): $$Q[t,t] = 1 \text{ for } t = 1, T$$ $$Q[t,t] = 2 \text{ for } 1 < t < T$$ $$Q[t,t-1] = Q[t-1,t] = -1$$

This is a rank-deficient matrix (rank T-1), so a sum-to-zero constraint is applied for identifiability.

Examples

# Create temporal RW1 specification
temporal_rw1("year")
#> tulpaRatio temporal specification
#> ============================
#> 
#> Type: RW1 (First-order Random Walk) 
#> Time variable: year 
#> Shared: Yes (enters both processes) 
temporal_rw1("month", cyclic = TRUE)
#> tulpaRatio temporal specification
#> ============================
#> 
#> Type: RW1 (First-order Random Walk) 
#> Time variable: month 
#> Cyclic: Yes
#> Shared: Yes (enters both processes) 

# \donttest{
# Simple temporal trend
set.seed(123)
df <- data.frame(
  year = rep(2010:2021, each = 4),
  x = rnorm(48),
  count = rpois(48, lambda = 20),
  effort = rgamma(48, shape = 5, rate = 1)
)

fit <- tratio(
  count | effort ~ x,
  data = df,
  family = ratiod_poisson_gamma(),
  temporal = temporal_rw1("year"),
  mode = "hmc",
  control = list(iter = 200, warmup = 100, chains = 1)
)
#> Inference: Exact (Tier 1)
#>   Backend: hmc
#> Fitting ratio model...
#>   Family: poisson_gamma
#>   Observations: 48
#>   Iterations: 200 (warmup: 100)
#>   Temporal: rw1 (12 time points)
#> Running NUTS sampler...
#>   Parameters: 18
#>   Iterations: 200 (warmup: 100)
#>   Chains: 1 (cores: 1)
#>   Temporal: rw1 (12 time points)

# Panel data: separate trends per site
set.seed(124)
df_panel <- data.frame(
  year = rep(2015:2026, each = 5),
  site = rep(paste0("site", 1:5), times = 12),
  x = rnorm(60),
  count = rpois(60, lambda = 15),
  effort = rgamma(60, shape = 3, rate = 1)
)

fit2 <- tratio(
  count | effort ~ x + (1 | site),
  data = df_panel,
  family = ratiod_poisson_gamma(),
  temporal = temporal_rw1("year", group_var = "site"),
  mode = "hmc",
  control = list(iter = 200, warmup = 100, chains = 1)
)
#> Inference: Exact (Tier 1)
#>   Backend: hmc
#> Fitting ratio model...
#>   Family: poisson_gamma
#>   Observations: 60
#>   Iterations: 200 (warmup: 100)
#>   Temporal: rw1 (12 time points)
#> Running NUTS sampler...
#>   Parameters: 72
#>   Iterations: 200 (warmup: 100)
#>   Chains: 1 (cores: 1)
#>   Temporal: rw1 (12 time points)

# Cyclic for monthly seasonal data
set.seed(125)
df_monthly <- data.frame(
  month = rep(1:12, times = 4),
  x = rnorm(48),
  count = rpois(48, lambda = 10),
  effort = rgamma(48, shape = 2, rate = 1)
)

fit3 <- tratio(
  count | effort ~ x,
  data = df_monthly,
  family = ratiod_poisson_gamma(),
  temporal = temporal_rw1("month", cyclic = TRUE),
  mode = "hmc",
  control = list(iter = 200, warmup = 100, chains = 1)
)
#> Inference: Exact (Tier 1)
#>   Backend: hmc
#> Fitting ratio model...
#>   Family: poisson_gamma
#>   Observations: 48
#>   Iterations: 200 (warmup: 100)
#>   Temporal: rw1 (12 time points)
#> Running NUTS sampler...
#>   Parameters: 18
#>   Iterations: 200 (warmup: 100)
#>   Chains: 1 (cores: 1)
#>   Temporal: rw1 (12 time points)
# }