diff --git a/.Rbuildignore b/.Rbuildignore new file mode 100644 index 0000000..3912071 --- /dev/null +++ b/.Rbuildignore @@ -0,0 +1,3 @@ +^.*\.Rproj$ +^\.Rproj\.user$ +^\.github$ diff --git a/.github/.gitignore b/.github/.gitignore new file mode 100644 index 0000000..2d19fc7 --- /dev/null +++ b/.github/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml new file mode 100644 index 0000000..5bef95c --- /dev/null +++ b/.github/workflows/R-CMD-check.yaml @@ -0,0 +1,28 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/master/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: R-CMD-check + +jobs: + R-CMD-check: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + steps: + - uses: actions/checkout@v2 + + - uses: r-lib/actions/setup-r@v1 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v1 + with: + extra-packages: rcmdcheck + + - uses: r-lib/actions/check-r-package@v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b079f20 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.Rproj.user +.Rhistory +.RData +.Ruserdata +src/*.o +src/*.so +src/*.dll +.DS_Store +project.Rproj diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..1e87ffa --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,45 @@ +Package: mvdlm +Title: Multivariate Dynamic Linear Modelling With Stan +Version: 0.1.0 +Authors@R: + c(person(given = "Eric J.", + family = "Ward", + role = c("aut", "cre"), + email = "eric.ward@noaa.gov", + comment = c(ORCID = "0000-0002-4359-0296"))) +Description: Fits multivariate dynamic linear models in a Bayesian framework using Stan. +License: GPL (>=3) +Encoding: UTF-8 +LazyData: true +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.2.1 +Biarch: true +URL: https://github.com/atsa-es/mvdlm +BugReports: https://github.com/atsa-es/mvdlm/issues +Depends: + R (>= 4.1.0) +Imports: + broom.mixed, + methods, + gtools, + compositions, + ggplot2, + MARSS, + Rcpp (>= 0.12.0), + RcppParallel (>= 5.0.1), + rstan (>= 2.18.1), + rstantools (>= 2.1.1) +Suggests: + testthat, + knitr, + rmarkdown, + parallel +LinkingTo: + BH (>= 1.66.0), + Rcpp (>= 0.12.0), + RcppEigen (>= 0.3.3.3.0), + RcppParallel (>= 5.0.1), + rstan (>= 2.18.1), + StanHeaders (>= 2.18.0) +SystemRequirements: GNU make +VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 0000000..a140184 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,13 @@ +# Generated by roxygen2: do not edit by hand + +export(dlm_trends) +export(fit_dlm) +import(Rcpp) +import(ggplot2) +import(methods) +importFrom(broom.mixed,tidy) +importFrom(rstan,sampling) +importFrom(stats,model.frame) +importFrom(stats,model.matrix) +importFrom(stats,model.response) +useDynLib(mvdlm, .registration = TRUE) diff --git a/R/dlm_trends.R b/R/dlm_trends.R new file mode 100644 index 0000000..374e797 --- /dev/null +++ b/R/dlm_trends.R @@ -0,0 +1,57 @@ +#' Summarize and plot time varying coefficients from the fitted model +#' +#' @param fitted_model A fitted model object +#' @export +#' @return A list containing the plot and data used +#' to fit the model. These include `plot` and `b_varying` + +#' @importFrom broom.mixed tidy +#' @import ggplot2 +#' +#' @examples +#' \donttest{ +#' set.seed(123) +#' N = 20 +#' data = data.frame("y" = runif(N), +#' "cov1" = rnorm(N), +#' "cov2" = rnorm(N), +#' "year" = 1:N, +#' "season" = sample(c("A","B"), size=N, replace=T)) +#' b_1 = cumsum(rnorm(N)) +#' b_2 = cumsum(rnorm(N)) +#' data$y = data$cov1*b_1 + data$cov2*b_2 +#' time_varying = y ~ cov1 + cov2 +#' formula = NULL +#' fit <- fit_dlm(formula = formula, +#' time_varying = time_varying, +#' time = "year", +#' est_df = FALSE, +#' family = c("normal"), +#' data, chains = 1, iter = 20) +#' dlm_trends(fit) +#' } +#' +dlm_trends <- function(fitted_model) { + + tidy_pars <- broom.mixed::tidy(fitted_model$fit) + + indx <- grep("b_varying", tidy_pars$term) + if(length(indx) == 0) { + stop("Error: time varying parameters not found") + } + + b_varying = tidy_pars[indx,] # subset + b_varying$par <- rep(fit$time_varying_pars, each = fit$stan_data$nT) # add names + b_varying$time <- rep(1:fit$stan_data$nT, length(fit$time_varying_pars)) + + cols <- "#440154FF" # viridis::viridis(1) + g <- ggplot(b_varying, aes(time, estimate)) + + geom_ribbon(aes(ymin=estimate-1.96*std.error, ymax=estimate+1.96*std.error), fill=cols, alpha=0.5) + + geom_line(col = cols) + + facet_wrap(~par, scales="free_y") + + ylab("Estimate") + + xlab("Time") + + theme_bw() + + theme(strip.background =element_rect(fill="white")) + return(list(plot = g, b_varying = b_varying)) +} diff --git a/R/fitting.R b/R/fitting.R new file mode 100644 index 0000000..3fc921d --- /dev/null +++ b/R/fitting.R @@ -0,0 +1,222 @@ +#' Fit a Bayesian Dirichlet regression model, allowing for zero-and-one inflation, covariates, and overdispersion +#' +#' Fit a Bayesian Dirichlet regression model that optionally includes covariates to estimate +#' effects of factor or continuous variables on proportions. +#' +#' @param formula The model formula for the fixed effects; at least this formula or `time_varying` needs to have the response included +#' @param time_varying The model formula for the time-varying effects; at least this formula or `formula` needs to have the response included +#' @param time String describing the name of the variable corresponding to time, defaults to "year" +#' @param est_df Whether or not to estimate deviaitions of B as Student - t with estimated degrees of freedom, defaults to `FALSE` +#' @param family, The name of the family used for the response; can be one of "normal","binomial","possion","nbinom2","gamma","lognormal" +#' @param correlated_rw, Whether to estimate time-varying parameters as correlated random walk, defaults to TRUE +#' @param data The data frame including response and covariates for all model components +#' @param chains Number of mcmc chains, defaults to 3 +#' @param iter Number of mcmc iterations, defaults to 2000 +#' @param warmup Number iterations for mcmc warmup, defaults to 1/2 of the iterations +#' @param ... Any other arguments to pass to [rstan::sampling()]. +#' @export +#' @return A list containing the fitted model and arguments and data used +#' to fit the model. These include `model` (the fitted model object of class `stanfit`), + +#' @importFrom rstan sampling +#' @importFrom stats model.frame model.matrix model.response +#' @import Rcpp +#' +#' @examples +#' \donttest{ +#' set.seed(123) +#' N = 20 +#' data = data.frame("y" = runif(N), +#' "cov1" = rnorm(N), +#' "cov2" = rnorm(N), +#' "year" = 1:N, +#' "season" = sample(c("A","B"), size=N, replace=TRUE)) +#' b_1 = cumsum(rnorm(N)) +#' b_2 = cumsum(rnorm(N)) +#' data$y = data$cov1*b_1 + data$cov2*b_2 +#' time_varying = y ~ cov1 + cov2 +#' formula = NULL +#' +#' # fit a model with a time varying component +#' fit <- fit_dlm(formula = formula, +#' time_varying = time_varying, +#' time = "year", +#' est_df = FALSE, +#' family = c("normal"), +#' data, chains = 1, iter = 20) +#' +#' # fit a model with a time varying and fixed component (here, fixed intercept) +#' fit <- fit_dlm(formula = y ~ 1, +#' time_varying = y ~ -1 + cov1 + cov2, +#' time = "year", +#' est_df = FALSE, +#' family = c("normal"), +#' data, chains = 1, iter = 20) +#' +#' #' # fit a model with deviations modeled with a multivariate Student-t +#' fit <- fit_dlm(formula = y ~ 1, +#' time_varying = y ~ -1 + cov1 + cov2, +#' time = "year", +#' est_df = TRUE, +#' family = c("normal"), +#' data, chains = 1, iter = 20) +#' +#' #' #' # fit a model with deviations modeled with a multivariate Student-t +#' fit <- fit_dlm(formula = y ~ 1, +#' time_varying = y ~ -1 + cov1 + cov2, +#' time = "year", +#' est_df = TRUE, +#' family = c("normal"), +#' data, chains = 1, iter = 20) +#' } +#' +fit_dlm <- function(formula = NULL, + time_varying = NULL, + time = "year", + est_df = FALSE, + family = c("normal", "binomial", "poisson", "nbinom2", "gamma", "lognormal"), + correlated_rw = TRUE, + data, + chains = 3, + iter = 2000, + warmup = floor(iter / 2), + ...) { + + # add intercept column to data + data$`(Intercept)` <- 1 + + recognized_families <- c("normal", "binomial", "poisson", "nbinom2", "gamma", "lognormal") + family <- family[1] + if (family %in% recognized_families == FALSE) { + stop("Error: family not recognized") + } else { + family <- match(family, recognized_families) + } + + # parse formulas + est_fixed_coef <- FALSE + est_varying_coef <- FALSE + n_fixed <- 0 + n_varying <- 0 + + y <- NULL + tv_pars <- NULL + fixed_pars <- NULL + if (!is.null(formula)) { + model_frame <- model.frame(formula, data, na.action=na.pass) + y <- model.response(model_frame) + model_matrix <- model.matrix(formula, model_frame) + fixed_pars <- colnames(model_matrix) + est_fixed_coef <- TRUE + fixed_dat <- cbind(model_matrix, c(data[, time])) + colnames(fixed_dat)[ncol(fixed_dat)] <- "time" + fixed_dat[,ncol(fixed_dat)] = fixed_dat[,ncol(fixed_dat)] - min(fixed_dat[,ncol(fixed_dat)]) + 1 + n_fixed <- ncol(fixed_dat) - 1 + fixed_time <- rep(fixed_dat[, "time"], ncol(fixed_dat) - 1) + fixed_var <- sort(rep(1:n_fixed, nrow(fixed_dat))) + fixed_x <- c(as.matrix(fixed_dat[, which(colnames(fixed_dat) != "time")])) + fixed_N <- length(fixed_time) + n_fixed_NAs <- length(which(is.na(fixed_x))) + fixed_NAs <- 0 # dummy + if (n_fixed_NAs > 0) { + fixed_NAs <- c(which(is.na(fixed_x)), 0, 0) + fixed_x[which(is.na(fixed_x))] = 0 + } else { + fixed_NAs <- c(0, 0) + } + } else { + n_fixed <- 0 + fixed_time <- c(0, 0) + fixed_var <- c(0, 0) + fixed_x <- c(0, 0) + fixed_N <- 2 + n_fixed_NAs <- 0 + fixed_NAs <- c(0, 0) # dummy + } + if (!is.null(time_varying)) { + model_frame <- model.frame(time_varying, data, na.action=na.pass) + if (is.null(y)) y <- model.response(model_frame) + model_matrix <- model.matrix(time_varying, model_frame) + tv_pars <- colnames(model_matrix) + est_varying_coef <- TRUE + varying_dat <- cbind(model_matrix, c(data[, time])) + colnames(varying_dat)[ncol(varying_dat)] <- "time" + varying_dat[,ncol(varying_dat)] <- varying_dat[,ncol(varying_dat)] - min(varying_dat[,ncol(varying_dat)]) + 1 + n_varying <- ncol(varying_dat) - 1 + varying_time <- rep(varying_dat[, "time"], ncol(varying_dat) - 1) + varying_var <- sort(rep(1:n_varying, nrow(varying_dat))) + varying_x <- c(as.matrix(varying_dat[, which(colnames(varying_dat) != "time")])) + varying_N <- length(varying_time) + n_varying_NAs <- length(which(is.na(varying_x))) + varying_NAs <- 0 # dummy + if (n_varying_NAs > 0) { + varying_NAs <- c(which(is.na(varying_x)), 0, 0) + varying_x[which(is.na(varying_x))] = 0 + } else { + varying_NAs <- c(0, 0) + } + } else { + n_varying <- 0 + varying_time <- 0 + varying_var <- 0 + varying_x <- 0 + varying_N <- 1 + n_varying_NAs <- 0 + varying_NAs <- c(0, 0) # dummy + } + + stan_data <- list( + y = y, + y_int = as.integer(y), + N = length(y), + nT = max(c(fixed_time, varying_time), na.rm = T), + est_fixed = as.numeric(est_fixed_coef), + est_varying = as.numeric(est_varying_coef), + n_fixed_covars = n_fixed, + fixed_N = fixed_N, + fixed_time_indx = fixed_time, + fixed_var_indx = fixed_var, + fixed_x_value = fixed_x, + n_varying_covars = n_varying, + varying_N = varying_N, + varying_time_indx = varying_time, + varying_var_indx = varying_var, + varying_x_value = varying_x, + est_df = as.numeric(est_df), + family = family, + n_fixed_NAs = n_fixed_NAs, + fixed_NAs = fixed_NAs, + n_varying_NAs = n_varying_NAs, + varying_NAs = varying_NAs, + correlated_rw = as.numeric(correlated_rw) + ) + + pars <- c("eta", "sigma", "log_lik", "lp__") + if(est_varying_coef == TRUE) pars <- c(pars, "b_varying") + if(est_fixed_coef == TRUE) pars <- c(pars, "b_fixed") + if(family %in% c("normal","negbin2","gamma","lognormal")) pars <- c(pars, "phi") + if(est_df == TRUE) pars <- c(pars, "nu") + if(correlated_rw == TRUE) pars <- c(pars, "R", "Sigma", "Lcorr") + + sampling_args <- list( + object = stanmodels$dlm, + chains = chains, + iter = iter, + warmup = warmup, + pars = pars, + data = stan_data, ... + ) + fit <- do.call(sampling, sampling_args) + + return(list( + fit = fit, + "fixed_pars" = fixed_pars, + "time_varying_pars" = tv_pars, + fixed_formula = formula, + time_varying_formula = time_varying, + time = time, + est_df = est_df, + stan_data = stan_data, + raw_data = data + )) +} diff --git a/R/mvdlm-package.R b/R/mvdlm-package.R new file mode 100644 index 0000000..454c36b --- /dev/null +++ b/R/mvdlm-package.R @@ -0,0 +1,16 @@ +#' The 'mvdlm' package. +#' +#' @description A DESCRIPTION OF THE PACKAGE +#' +#' @docType package +#' @name mvdlm-package +#' @aliases mvdlm +#' @useDynLib mvdlm, .registration = TRUE +#' @import methods +#' @import Rcpp +#' @importFrom rstan sampling +#' +#' @references +#' Stan Development Team (2020). RStan: the R interface to Stan. R package version 2.21.2. https://mc-stan.org +#' +NULL diff --git a/R/stanmodels.R b/R/stanmodels.R new file mode 100644 index 0000000..4205531 --- /dev/null +++ b/R/stanmodels.R @@ -0,0 +1,25 @@ +# Generated by rstantools. Do not edit by hand. + +# names of stan models +stanmodels <- c("dlm") + +# load each stan module +Rcpp::loadModule("stan_fit4dlm_mod", what = TRUE) + +# instantiate each stanmodel object +stanmodels <- sapply(stanmodels, function(model_name) { + # create C++ code for stan model + stan_file <- if(dir.exists("stan")) "stan" else file.path("inst", "stan") + stan_file <- file.path(stan_file, paste0(model_name, ".stan")) + stanfit <- rstan::stanc_builder(stan_file, + allow_undefined = TRUE, + obfuscate_model_name = FALSE) + stanfit$model_cpp <- list(model_cppname = stanfit$model_name, + model_cppcode = stanfit$cppcode) + # create stanmodel object + methods::new(Class = "stanmodel", + model_name = stanfit$model_name, + model_code = stanfit$model_code, + model_cpp = stanfit$model_cpp, + mk_cppmodule = function(x) get(paste0("model_", model_name))) +}) diff --git a/README.Rmd b/README.Rmd new file mode 100644 index 0000000..d202316 --- /dev/null +++ b/README.Rmd @@ -0,0 +1,36 @@ +--- +output: github_document +--- + + + +```{r, echo = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.path = "README-figs/", + cache.path = "README-cache/" +) +``` + +# mvdlm + + + [![R-CMD-check](https://github.com/atsa-es/mvdlm/workflows/R-CMD-check/badge.svg)](https://github.com/atsa-es/mvdlm/actions) + + +mvdlm implements multivariate dynamic linear models (DLMs) in a Bayesian framework (Stan). Check out the documentation site: [https://atsa-es.github.io/mvdlm/](https://atsa-es.github.io/mvdlm/) + +You can install the development version of the package with: + +```{r, eval=FALSE} +remotes::install_github("atsa-es/mvdlm") +``` + +### NOAA Disclaimer + +This repository is a scientific product and is not official communication of the National Oceanic and Atmospheric Administration, or the United States Department of Commerce. All NOAA GitHub project code is provided on an ‘as is’ basis and the user assumes responsibility for its use. Any claims against the Department of Commerce or Department of Commerce bureaus stemming from the use of this GitHub project will be governed by all applicable Federal law. Any reference to specific commercial products, processes, or services by service mark, trademark, manufacturer, or otherwise, does not constitute or imply their endorsement, recommendation or favoring by the Department of Commerce. The Department of Commerce seal and logo, or the seal and logo of a DOC bureau, shall not be used in any manner to imply endorsement of any commercial product or activity by DOC or the United States Government. + +NOAA Fisheries + +[U.S. Department of Commerce](https://www.commerce.gov/) | [National Oceanographic and Atmospheric Administration](https://www.noaa.gov) | [NOAA Fisheries](https://www.fisheries.noaa.gov/) diff --git a/README.md b/README.md new file mode 100644 index 0000000..a76ee7f --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ + + + +# mvdlm + + +[![R-CMD-check](https://github.com/atsa-es/mvdlm/workflows/R-CMD-check/badge.svg)](https://github.com/atsa-es/mvdlm/actions) + + +mvdlm implements multivariate dynamic linear models (DLMs) in a Bayesian +framework (Stan). Check out the documentation site: + + +You can install the development version of the package with: + +``` r +remotes::install_github("atsa-es/mvdlm") +``` + +### NOAA Disclaimer + +This repository is a scientific product and is not official +communication of the National Oceanic and Atmospheric Administration, or +the United States Department of Commerce. All NOAA GitHub project code +is provided on an ‘as is’ basis and the user assumes responsibility for +its use. Any claims against the Department of Commerce or Department of +Commerce bureaus stemming from the use of this GitHub project will be +governed by all applicable Federal law. Any reference to specific +commercial products, processes, or services by service mark, trademark, +manufacturer, or otherwise, does not constitute or imply their +endorsement, recommendation or favoring by the Department of Commerce. +The Department of Commerce seal and logo, or the seal and logo of a DOC +bureau, shall not be used in any manner to imply endorsement of any +commercial product or activity by DOC or the United States Government. + +NOAA Fisheries + +[U.S. Department of Commerce](https://www.commerce.gov/) \| [National +Oceanographic and Atmospheric Administration](https://www.noaa.gov) \| +[NOAA Fisheries](https://www.fisheries.noaa.gov/) diff --git a/configure b/configure new file mode 100755 index 0000000..1c04798 --- /dev/null +++ b/configure @@ -0,0 +1,4 @@ +# Generated by rstantools. Do not edit by hand. + +#! /bin/sh +"${R_HOME}/bin/Rscript" -e "rstantools::rstan_config()" diff --git a/configure.win b/configure.win new file mode 100755 index 0000000..94d77bd --- /dev/null +++ b/configure.win @@ -0,0 +1,4 @@ +# Generated by rstantools. Do not edit by hand. + +#! /bin/sh +"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "rstantools::rstan_config()" diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 0000000..5647a89 --- /dev/null +++ b/docs/404.html @@ -0,0 +1,112 @@ + + + + + + + +Page not found (404) • mvdlm + + + + + + + + + + + +
+
+ + + + +
+
+ + +Content not found. Please use links in the navbar. + +
+ + + +
+ + + +
+ +
+

+

Site built with pkgdown 2.0.2.

+
+ +
+
+ + + + + + + + diff --git a/docs/articles/a01_overview.html b/docs/articles/a01_overview.html new file mode 100644 index 0000000..5846fcc --- /dev/null +++ b/docs/articles/a01_overview.html @@ -0,0 +1,298 @@ + + + + + + + +Overview of mvdlm package • mvdlm + + + + + + + + + + + + +
+
+ + + + +
+
+ + + + +
+

Overview +

+

For examples, we’re going to use one of the same datasets that are widely documented in the MARSS manual. This data consists of three columns, * year, representing the year of the observation * logit.s, representing logit-transformed survival of Columbia River salmon * CUI.apr, representing coastal upwelling index values in April

+ +
## This is loo version 2.4.1
+
## - Online documentation and vignettes at mc-stan.org/loo
+
## - As of v2.0.0 loo defaults to 1 core but we recommend using as many as possible. Use the 'cores' argument or set options(mc.cores = NUM_CORES) for an entire session.
+
+data(SalmonSurvCUI)
+head(SalmonSurvCUI)
+
##   year logit.s CUI.apr
+## 1 1964   -3.46      57
+## 2 1965   -3.32       5
+## 3 1966   -3.58      43
+## 4 1967   -3.03      11
+## 5 1968   -3.61      47
+## 6 1969   -3.35     -21
+
+g1 <- ggplot(SalmonSurvCUI, aes(year, logit.s)) + 
+  geom_point() + 
+  geom_line()
+g1
+

+
+g2 <- ggplot(SalmonSurvCUI, aes(year, CUI.apr)) + 
+  geom_point() + 
+  geom_line()
+g2
+

+
+
+

Model 1: time varying intercept and slope +

+

For a first model, we’ll fit the same model used in the MARSS manual, with a time varying intercept and time varying coefficient on CUI. We can specify these time varying effects using the time_varying argument. Note an intercept is not included, like with lm, glm, and similar packages this the intercept is implicitly included. Note that alternatively you could specify this formula as time_varying = logit.s ~ 1 + CUI.apr, where we add the extra 1 to signify the intercept.

+

Like the MARSS example, we also standardize the covariates,

+
+SalmonSurvCUI$CUI.apr = scale(SalmonSurvCUI$CUI.apr)
+
+fit <- fit_dlm(time_varying = logit.s ~ CUI.apr,
+        data = SalmonSurvCUI,
+        chains=1,
+        iter=1000)
+
## 
+## SAMPLING FOR MODEL 'dlm' NOW (CHAIN 1).
+## Chain 1: 
+## Chain 1: Gradient evaluation took 0.000211 seconds
+## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 2.11 seconds.
+## Chain 1: Adjust your expectations accordingly!
+## Chain 1: 
+## Chain 1: 
+## Chain 1: Iteration:   1 / 1000 [  0%]  (Warmup)
+## Chain 1: Iteration: 100 / 1000 [ 10%]  (Warmup)
+## Chain 1: Iteration: 200 / 1000 [ 20%]  (Warmup)
+## Chain 1: Iteration: 300 / 1000 [ 30%]  (Warmup)
+## Chain 1: Iteration: 400 / 1000 [ 40%]  (Warmup)
+## Chain 1: Iteration: 500 / 1000 [ 50%]  (Warmup)
+## Chain 1: Iteration: 501 / 1000 [ 50%]  (Sampling)
+## Chain 1: Iteration: 600 / 1000 [ 60%]  (Sampling)
+## Chain 1: Iteration: 700 / 1000 [ 70%]  (Sampling)
+## Chain 1: Iteration: 800 / 1000 [ 80%]  (Sampling)
+## Chain 1: Iteration: 900 / 1000 [ 90%]  (Sampling)
+## Chain 1: Iteration: 1000 / 1000 [100%]  (Sampling)
+## Chain 1: 
+## Chain 1:  Elapsed Time: 13.1411 seconds (Warm-up)
+## Chain 1:                8.21075 seconds (Sampling)
+## Chain 1:                21.3519 seconds (Total)
+## Chain 1:
+
## Warning: There were 18 divergent transitions after warmup. See
+## https://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
+## to find out why this is a problem and how to eliminate them.
+
## Warning: There were 1 chains where the estimated Bayesian Fraction of Missing Information was low. See
+## https://mc-stan.org/misc/warnings.html#bfmi-low
+
## Warning: Examine the pairs() plot to diagnose sampling problems
+
## Warning: The largest R-hat is NA, indicating chains have not mixed.
+## Running the chains for more iterations may help. See
+## https://mc-stan.org/misc/warnings.html#r-hat
+
## Warning: Bulk Effective Samples Size (ESS) is too low, indicating posterior means and medians may be unreliable.
+## Running the chains for more iterations may help. See
+## https://mc-stan.org/misc/warnings.html#bulk-ess
+
## Warning: Tail Effective Samples Size (ESS) is too low, indicating posterior variances and tail quantiles may be unreliable.
+## Running the chains for more iterations may help. See
+## https://mc-stan.org/misc/warnings.html#tail-ess
+

With only 1000 iterations and 1 chain, we might not expect the model to converge (see additional guidance via Stan developers here: https://mc-stan.org/misc/warnings.html). A couple things to consider:

+
    +
  • Did you get any warnings about divergent transitions after warmup? If so, try increasing the iterations / burn-in period, and number of chains. It’s also worth increasing the value of adapt_delta. (this will slow the sampling down a little). If you’re still getting these warnings, the model may be mis-specified or data not informative.
  • +
+
+fit <- fit_dlm(time_varying = logit.s ~ CUI.apr,
+        data = SalmonSurvCUI,
+        chains=1,
+        iter=1000,
+        control = list(adapt_delta=0.99))
+
    +
  • Did you get a warning about the maximum tree depth? If so, you can increase the maximum tree (max_treedepth) depth with the following
  • +
+
+fit <- fit_dlm(time_varying = logit.s ~ CUI.apr,
+        data = SalmonSurvCUI,
+        chains=1,
+        iter=1000,
+        control = list(max_treedepth=15))
+

We can extract tidied versions of any of the parameters with

+
+broom.mixed::tidy(fit$fit)
+
## # A tibble: 182 × 3
+##    term    estimate std.error
+##    <chr>      <dbl>     <dbl>
+##  1 eta[1]     -3.38     0.327
+##  2 eta[2]     -3.16     0.302
+##  3 eta[3]     -3.52     0.291
+##  4 eta[4]     -3.21     0.272
+##  5 eta[5]     -3.67     0.299
+##  6 eta[6]     -3.43     0.314
+##  7 eta[7]     -3.97     0.272
+##  8 eta[8]     -4.26     0.264
+##  9 eta[9]     -4.70     0.276
+## 10 eta[10]    -5.18     0.401
+## # … with 172 more rows
+## # ℹ Use `print(n = ...)` to see more rows
+

We also have a helper function for extracting and visualizing trends for time varying parameters.

+ +
## $plot
+

+
## 
+## $b_varying
+## # A tibble: 84 × 5
+##    term            estimate std.error par          time
+##    <chr>              <dbl>     <dbl> <chr>       <int>
+##  1 b_varying[1,1]     -2.75     0.475 (Intercept)     1
+##  2 b_varying[2,1]     -3.15     0.305 (Intercept)     2
+##  3 b_varying[3,1]     -3.17     0.347 (Intercept)     3
+##  4 b_varying[4,1]     -3.16     0.297 (Intercept)     4
+##  5 b_varying[5,1]     -3.39     0.310 (Intercept)     5
+##  6 b_varying[6,1]     -3.59     0.274 (Intercept)     6
+##  7 b_varying[7,1]     -3.87     0.280 (Intercept)     7
+##  8 b_varying[8,1]     -4.30     0.259 (Intercept)     8
+##  9 b_varying[9,1]     -4.71     0.269 (Intercept)     9
+## 10 b_varying[10,1]    -5.01     0.356 (Intercept)    10
+## # … with 74 more rows
+## # ℹ Use `print(n = ...)` to see more rows
+

This function returns a plot and the values used to make the plot (b_varying)

+
+
+

Model 2: time varying intercept and constant slope +

+

As a second example, we could fit a model with a constant effect of CUI, but a time varying slope. The fit_dlm function has two formula parameters, formula for static effects, and time_varying for time varying ones. This model is specified as

+
+fit <- fit_dlm(time_varying = logit.s ~ 1,
+               formula = logit.s ~ CUI.apr,
+        data = SalmonSurvCUI,
+        chains=1,
+        iter=1000)
+
+
+

Model 3: constant intercept and time varying slope +

+

We could do the same with a model that had a time varying effect of CUI, but a time constant slope.

+
+fit <- fit_dlm(time_varying = logit.s ~ CUI.apr,
+               formula = logit.s ~ 1,
+        data = SalmonSurvCUI,
+        chains=1,
+        iter=1000)
+
+
+

Comparing models +

+

All three of the above formulations of the DLM can be compared with the loo package, and statistics such as LOOIC can be easily calculated. For example,

+
+library(loo)
+loo::loo(fit$fit)
+
+
+ + + +
+ + + +
+ +
+

+

Site built with pkgdown 2.0.2.

+
+ +
+
+ + + + + + + + diff --git a/docs/articles/a01_overview_files/figure-html/unnamed-chunk-2-1.png b/docs/articles/a01_overview_files/figure-html/unnamed-chunk-2-1.png new file mode 100644 index 0000000..f0246f5 Binary files /dev/null and b/docs/articles/a01_overview_files/figure-html/unnamed-chunk-2-1.png differ diff --git a/docs/articles/a01_overview_files/figure-html/unnamed-chunk-3-1.png b/docs/articles/a01_overview_files/figure-html/unnamed-chunk-3-1.png new file mode 100644 index 0000000..b8c8bf6 Binary files /dev/null and b/docs/articles/a01_overview_files/figure-html/unnamed-chunk-3-1.png differ diff --git a/docs/articles/a01_overview_files/figure-html/unnamed-chunk-8-1.png b/docs/articles/a01_overview_files/figure-html/unnamed-chunk-8-1.png new file mode 100644 index 0000000..6c45982 Binary files /dev/null and b/docs/articles/a01_overview_files/figure-html/unnamed-chunk-8-1.png differ diff --git a/docs/articles/index.html b/docs/articles/index.html new file mode 100644 index 0000000..16e3211 --- /dev/null +++ b/docs/articles/index.html @@ -0,0 +1,83 @@ + +Articles • mvdlm + + +
+
+ + + +
+
+ + +
+

All vignettes

+

+ +
Overview of mvdlm package
+
+
+
+
+ + +
+ +
+

Site built with pkgdown 2.0.2.

+
+ +
+ + + + + + + + diff --git a/docs/authors.html b/docs/authors.html new file mode 100644 index 0000000..f6e5f60 --- /dev/null +++ b/docs/authors.html @@ -0,0 +1,105 @@ + +Authors and Citation • mvdlm + + +
+
+ + + +
+
+
+ + + +
  • +

    Eric J. Ward. Author, maintainer. +

    +
  • +
+
+
+

Citation

+ Source: DESCRIPTION +
+
+ + +

Ward E (2022). +mvdlm: Multivariate Dynamic Linear Modelling With Stan. +R package version 0.1.0, https://github.com/atsa-es/mvdlm. +

+
@Manual{,
+  title = {mvdlm: Multivariate Dynamic Linear Modelling With Stan},
+  author = {Eric J. Ward},
+  year = {2022},
+  note = {R package version 0.1.0},
+  url = {https://github.com/atsa-es/mvdlm},
+}
+ +
+ +
+ + + +
+ +
+

Site built with pkgdown 2.0.2.

+
+ +
+ + + + + + + + diff --git a/docs/bootstrap-toc.css b/docs/bootstrap-toc.css new file mode 100644 index 0000000..5a85941 --- /dev/null +++ b/docs/bootstrap-toc.css @@ -0,0 +1,60 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ + +/* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ + +/* All levels of nav */ +nav[data-toggle='toc'] .nav > li > a { + display: block; + padding: 4px 20px; + font-size: 13px; + font-weight: 500; + color: #767676; +} +nav[data-toggle='toc'] .nav > li > a:hover, +nav[data-toggle='toc'] .nav > li > a:focus { + padding-left: 19px; + color: #563d7c; + text-decoration: none; + background-color: transparent; + border-left: 1px solid #563d7c; +} +nav[data-toggle='toc'] .nav > .active > a, +nav[data-toggle='toc'] .nav > .active:hover > a, +nav[data-toggle='toc'] .nav > .active:focus > a { + padding-left: 18px; + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-left: 2px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +nav[data-toggle='toc'] .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} +nav[data-toggle='toc'] .nav .nav > li > a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 30px; + font-size: 12px; + font-weight: normal; +} +nav[data-toggle='toc'] .nav .nav > li > a:hover, +nav[data-toggle='toc'] .nav .nav > li > a:focus { + padding-left: 29px; +} +nav[data-toggle='toc'] .nav .nav > .active > a, +nav[data-toggle='toc'] .nav .nav > .active:hover > a, +nav[data-toggle='toc'] .nav .nav > .active:focus > a { + padding-left: 28px; + font-weight: 500; +} + +/* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ +nav[data-toggle='toc'] .nav > .active > ul { + display: block; +} diff --git a/docs/bootstrap-toc.js b/docs/bootstrap-toc.js new file mode 100644 index 0000000..1cdd573 --- /dev/null +++ b/docs/bootstrap-toc.js @@ -0,0 +1,159 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ +(function() { + 'use strict'; + + window.Toc = { + helpers: { + // return all matching elements in the set, or their descendants + findOrFilter: function($el, selector) { + // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ + // http://stackoverflow.com/a/12731439/358804 + var $descendants = $el.find(selector); + return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); + }, + + generateUniqueIdBase: function(el) { + var text = $(el).text(); + var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); + return anchor || el.tagName.toLowerCase(); + }, + + generateUniqueId: function(el) { + var anchorBase = this.generateUniqueIdBase(el); + for (var i = 0; ; i++) { + var anchor = anchorBase; + if (i > 0) { + // add suffix + anchor += '-' + i; + } + // check if ID already exists + if (!document.getElementById(anchor)) { + return anchor; + } + } + }, + + generateAnchor: function(el) { + if (el.id) { + return el.id; + } else { + var anchor = this.generateUniqueId(el); + el.id = anchor; + return anchor; + } + }, + + createNavList: function() { + return $(''); + }, + + createChildNavList: function($parent) { + var $childList = this.createNavList(); + $parent.append($childList); + return $childList; + }, + + generateNavEl: function(anchor, text) { + var $a = $(''); + $a.attr('href', '#' + anchor); + $a.text(text); + var $li = $('
  • '); + $li.append($a); + return $li; + }, + + generateNavItem: function(headingEl) { + var anchor = this.generateAnchor(headingEl); + var $heading = $(headingEl); + var text = $heading.data('toc-text') || $heading.text(); + return this.generateNavEl(anchor, text); + }, + + // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). + getTopLevel: function($scope) { + for (var i = 1; i <= 6; i++) { + var $headings = this.findOrFilter($scope, 'h' + i); + if ($headings.length > 1) { + return i; + } + } + + return 1; + }, + + // returns the elements for the top level, and the next below it + getHeadings: function($scope, topLevel) { + var topSelector = 'h' + topLevel; + + var secondaryLevel = topLevel + 1; + var secondarySelector = 'h' + secondaryLevel; + + return this.findOrFilter($scope, topSelector + ',' + secondarySelector); + }, + + getNavLevel: function(el) { + return parseInt(el.tagName.charAt(1), 10); + }, + + populateNav: function($topContext, topLevel, $headings) { + var $context = $topContext; + var $prevNav; + + var helpers = this; + $headings.each(function(i, el) { + var $newNav = helpers.generateNavItem(el); + var navLevel = helpers.getNavLevel(el); + + // determine the proper $context + if (navLevel === topLevel) { + // use top level + $context = $topContext; + } else if ($prevNav && $context === $topContext) { + // create a new level of the tree and switch to it + $context = helpers.createChildNavList($prevNav); + } // else use the current $context + + $context.append($newNav); + + $prevNav = $newNav; + }); + }, + + parseOps: function(arg) { + var opts; + if (arg.jquery) { + opts = { + $nav: arg + }; + } else { + opts = arg; + } + opts.$scope = opts.$scope || $(document.body); + return opts; + } + }, + + // accepts a jQuery object, or an options object + init: function(opts) { + opts = this.helpers.parseOps(opts); + + // ensure that the data attribute is in place for styling + opts.$nav.attr('data-toggle', 'toc'); + + var $topContext = this.helpers.createChildNavList(opts.$nav); + var topLevel = this.helpers.getTopLevel(opts.$scope); + var $headings = this.helpers.getHeadings(opts.$scope, topLevel); + this.helpers.populateNav($topContext, topLevel, $headings); + } + }; + + $(function() { + $('nav[data-toggle="toc"]').each(function(i, el) { + var $nav = $(el); + Toc.init($nav); + }); + }); +})(); diff --git a/docs/docsearch.css b/docs/docsearch.css new file mode 100644 index 0000000..e5f1fe1 --- /dev/null +++ b/docs/docsearch.css @@ -0,0 +1,148 @@ +/* Docsearch -------------------------------------------------------------- */ +/* + Source: https://github.com/algolia/docsearch/ + License: MIT +*/ + +.algolia-autocomplete { + display: block; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.algolia-autocomplete .ds-dropdown-menu { + width: 100%; + min-width: none; + max-width: none; + padding: .75rem 0; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .1); + box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); +} + +@media (min-width:768px) { + .algolia-autocomplete .ds-dropdown-menu { + width: 175% + } +} + +.algolia-autocomplete .ds-dropdown-menu::before { + display: none +} + +.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] { + padding: 0; + background-color: rgb(255,255,255); + border: 0; + max-height: 80vh; +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestions { + margin-top: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion { + padding: 0; + overflow: visible +} + +.algolia-autocomplete .algolia-docsearch-suggestion--category-header { + padding: .125rem 1rem; + margin-top: 0; + font-size: 1.3em; + font-weight: 500; + color: #00008B; + border-bottom: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--wrapper { + float: none; + padding-top: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { + float: none; + width: auto; + padding: 0; + text-align: left +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content { + float: none; + width: auto; + padding: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content::before { + display: none +} + +.algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header { + padding-top: .75rem; + margin-top: .75rem; + border-top: 1px solid rgba(0, 0, 0, .1) +} + +.algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column { + display: block; + padding: .1rem 1rem; + margin-bottom: 0.1; + font-size: 1.0em; + font-weight: 400 + /* display: none */ +} + +.algolia-autocomplete .algolia-docsearch-suggestion--title { + display: block; + padding: .25rem 1rem; + margin-bottom: 0; + font-size: 0.9em; + font-weight: 400 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--text { + padding: 0 1rem .5rem; + margin-top: -.25rem; + font-size: 0.8em; + font-weight: 400; + line-height: 1.25 +} + +.algolia-autocomplete .algolia-docsearch-footer { + width: 110px; + height: 20px; + z-index: 3; + margin-top: 10.66667px; + float: right; + font-size: 0; + line-height: 0; +} + +.algolia-autocomplete .algolia-docsearch-footer--logo { + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-position: 50%; + background-size: 100%; + overflow: hidden; + text-indent: -9000px; + width: 100%; + height: 100%; + display: block; + transform: translate(-8px); +} + +.algolia-autocomplete .algolia-docsearch-suggestion--highlight { + color: #FF8C00; + background: rgba(232, 189, 54, 0.1) +} + + +.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { + box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5) +} + +.algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { + background-color: rgba(192, 192, 192, .15) +} diff --git a/docs/docsearch.js b/docs/docsearch.js new file mode 100644 index 0000000..b35504c --- /dev/null +++ b/docs/docsearch.js @@ -0,0 +1,85 @@ +$(function() { + + // register a handler to move the focus to the search bar + // upon pressing shift + "/" (i.e. "?") + $(document).on('keydown', function(e) { + if (e.shiftKey && e.keyCode == 191) { + e.preventDefault(); + $("#search-input").focus(); + } + }); + + $(document).ready(function() { + // do keyword highlighting + /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ + var mark = function() { + + var referrer = document.URL ; + var paramKey = "q" ; + + if (referrer.indexOf("?") !== -1) { + var qs = referrer.substr(referrer.indexOf('?') + 1); + var qs_noanchor = qs.split('#')[0]; + var qsa = qs_noanchor.split('&'); + var keyword = ""; + + for (var i = 0; i < qsa.length; i++) { + var currentParam = qsa[i].split('='); + + if (currentParam.length !== 2) { + continue; + } + + if (currentParam[0] == paramKey) { + keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); + } + } + + if (keyword !== "") { + $(".contents").unmark({ + done: function() { + $(".contents").mark(keyword); + } + }); + } + } + }; + + mark(); + }); +}); + +/* Search term highlighting ------------------------------*/ + +function matchedWords(hit) { + var words = []; + + var hierarchy = hit._highlightResult.hierarchy; + // loop to fetch from lvl0, lvl1, etc. + for (var idx in hierarchy) { + words = words.concat(hierarchy[idx].matchedWords); + } + + var content = hit._highlightResult.content; + if (content) { + words = words.concat(content.matchedWords); + } + + // return unique words + var words_uniq = [...new Set(words)]; + return words_uniq; +} + +function updateHitURL(hit) { + + var words = matchedWords(hit); + var url = ""; + + if (hit.anchor) { + url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; + } else { + url = hit.url + '?q=' + escape(words.join(" ")); + } + + return url; +} diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..7a4756d --- /dev/null +++ b/docs/index.html @@ -0,0 +1,157 @@ + + + + + + + +Multivariate Dynamic Linear Modelling With Stan • mvdlm + + + + + + + + + + + + +
    +
    + + + + +
    +
    +
    + + + +

    mvdlm implements multivariate dynamic linear models (DLMs) in a Bayesian framework (Stan)

    +

    You can install the development version of the package with:

    +
    +remotes::install_github("atsa-es/mvdlm")
    +
    +

    NOAA Disclaimer +

    +

    This repository is a scientific product and is not official communication of the National Oceanic and Atmospheric Administration, or the United States Department of Commerce. All NOAA GitHub project code is provided on an ‘as is’ basis and the user assumes responsibility for its use. Any claims against the Department of Commerce or Department of Commerce bureaus stemming from the use of this GitHub project will be governed by all applicable Federal law. Any reference to specific commercial products, processes, or services by service mark, trademark, manufacturer, or otherwise, does not constitute or imply their endorsement, recommendation or favoring by the Department of Commerce. The Department of Commerce seal and logo, or the seal and logo of a DOC bureau, shall not be used in any manner to imply endorsement of any commercial product or activity by DOC or the United States Government.

    +

    NOAA Fisheries

    +

    U.S. Department of Commerce | National Oceanographic and Atmospheric Administration | NOAA Fisheries

    +
    +
    +
    + + +
    + + +
    + +
    +

    +

    Site built with pkgdown 2.0.2.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/link.svg b/docs/link.svg new file mode 100644 index 0000000..88ad827 --- /dev/null +++ b/docs/link.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/docs/pkgdown.css b/docs/pkgdown.css new file mode 100644 index 0000000..80ea5b8 --- /dev/null +++ b/docs/pkgdown.css @@ -0,0 +1,384 @@ +/* Sticky footer */ + +/** + * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ + * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css + * + * .Site -> body > .container + * .Site-content -> body > .container .row + * .footer -> footer + * + * Key idea seems to be to ensure that .container and __all its parents__ + * have height set to 100% + * + */ + +html, body { + height: 100%; +} + +body { + position: relative; +} + +body > .container { + display: flex; + height: 100%; + flex-direction: column; +} + +body > .container .row { + flex: 1 0 auto; +} + +footer { + margin-top: 45px; + padding: 35px 0 36px; + border-top: 1px solid #e5e5e5; + color: #666; + display: flex; + flex-shrink: 0; +} +footer p { + margin-bottom: 0; +} +footer div { + flex: 1; +} +footer .pkgdown { + text-align: right; +} +footer p { + margin-bottom: 0; +} + +img.icon { + float: right; +} + +/* Ensure in-page images don't run outside their container */ +.contents img { + max-width: 100%; + height: auto; +} + +/* Fix bug in bootstrap (only seen in firefox) */ +summary { + display: list-item; +} + +/* Typographic tweaking ---------------------------------*/ + +.contents .page-header { + margin-top: calc(-60px + 1em); +} + +dd { + margin-left: 3em; +} + +/* Section anchors ---------------------------------*/ + +a.anchor { + display: none; + margin-left: 5px; + width: 20px; + height: 20px; + + background-image: url(./link.svg); + background-repeat: no-repeat; + background-size: 20px 20px; + background-position: center center; +} + +h1:hover .anchor, +h2:hover .anchor, +h3:hover .anchor, +h4:hover .anchor, +h5:hover .anchor, +h6:hover .anchor { + display: inline-block; +} + +/* Fixes for fixed navbar --------------------------*/ + +.contents h1, .contents h2, .contents h3, .contents h4 { + padding-top: 60px; + margin-top: -40px; +} + +/* Navbar submenu --------------------------*/ + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu>.dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover>.dropdown-menu { + display: block; +} + +.dropdown-submenu>a:after { + display: block; + content: " "; + float: right; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 5px 0 5px 5px; + border-left-color: #cccccc; + margin-top: 5px; + margin-right: -10px; +} + +.dropdown-submenu:hover>a:after { + border-left-color: #ffffff; +} + +.dropdown-submenu.pull-left { + float: none; +} + +.dropdown-submenu.pull-left>.dropdown-menu { + left: -100%; + margin-left: 10px; + border-radius: 6px 0 6px 6px; +} + +/* Sidebar --------------------------*/ + +#pkgdown-sidebar { + margin-top: 30px; + position: -webkit-sticky; + position: sticky; + top: 70px; +} + +#pkgdown-sidebar h2 { + font-size: 1.5em; + margin-top: 1em; +} + +#pkgdown-sidebar h2:first-child { + margin-top: 0; +} + +#pkgdown-sidebar .list-unstyled li { + margin-bottom: 0.5em; +} + +/* bootstrap-toc tweaks ------------------------------------------------------*/ + +/* All levels of nav */ + +nav[data-toggle='toc'] .nav > li > a { + padding: 4px 20px 4px 6px; + font-size: 1.5rem; + font-weight: 400; + color: inherit; +} + +nav[data-toggle='toc'] .nav > li > a:hover, +nav[data-toggle='toc'] .nav > li > a:focus { + padding-left: 5px; + color: inherit; + border-left: 1px solid #878787; +} + +nav[data-toggle='toc'] .nav > .active > a, +nav[data-toggle='toc'] .nav > .active:hover > a, +nav[data-toggle='toc'] .nav > .active:focus > a { + padding-left: 5px; + font-size: 1.5rem; + font-weight: 400; + color: inherit; + border-left: 2px solid #878787; +} + +/* Nav: second level (shown on .active) */ + +nav[data-toggle='toc'] .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} + +nav[data-toggle='toc'] .nav .nav > li > a { + padding-left: 16px; + font-size: 1.35rem; +} + +nav[data-toggle='toc'] .nav .nav > li > a:hover, +nav[data-toggle='toc'] .nav .nav > li > a:focus { + padding-left: 15px; +} + +nav[data-toggle='toc'] .nav .nav > .active > a, +nav[data-toggle='toc'] .nav .nav > .active:hover > a, +nav[data-toggle='toc'] .nav .nav > .active:focus > a { + padding-left: 15px; + font-weight: 500; + font-size: 1.35rem; +} + +/* orcid ------------------------------------------------------------------- */ + +.orcid { + font-size: 16px; + color: #A6CE39; + /* margins are required by official ORCID trademark and display guidelines */ + margin-left:4px; + margin-right:4px; + vertical-align: middle; +} + +/* Reference index & topics ----------------------------------------------- */ + +.ref-index th {font-weight: normal;} + +.ref-index td {vertical-align: top; min-width: 100px} +.ref-index .icon {width: 40px;} +.ref-index .alias {width: 40%;} +.ref-index-icons .alias {width: calc(40% - 40px);} +.ref-index .title {width: 60%;} + +.ref-arguments th {text-align: right; padding-right: 10px;} +.ref-arguments th, .ref-arguments td {vertical-align: top; min-width: 100px} +.ref-arguments .name {width: 20%;} +.ref-arguments .desc {width: 80%;} + +/* Nice scrolling for wide elements --------------------------------------- */ + +table { + display: block; + overflow: auto; +} + +/* Syntax highlighting ---------------------------------------------------- */ + +pre, code, pre code { + background-color: #f8f8f8; + color: #333; +} +pre, pre code { + white-space: pre-wrap; + word-break: break-all; + overflow-wrap: break-word; +} + +pre { + border: 1px solid #eee; +} + +pre .img, pre .r-plt { + margin: 5px 0; +} + +pre .img img, pre .r-plt img { + background-color: #fff; +} + +code a, pre a { + color: #375f84; +} + +a.sourceLine:hover { + text-decoration: none; +} + +.fl {color: #1514b5;} +.fu {color: #000000;} /* function */ +.ch,.st {color: #036a07;} /* string */ +.kw {color: #264D66;} /* keyword */ +.co {color: #888888;} /* comment */ + +.error {font-weight: bolder;} +.warning {font-weight: bolder;} + +/* Clipboard --------------------------*/ + +.hasCopyButton { + position: relative; +} + +.btn-copy-ex { + position: absolute; + right: 0; + top: 0; + visibility: hidden; +} + +.hasCopyButton:hover button.btn-copy-ex { + visibility: visible; +} + +/* headroom.js ------------------------ */ + +.headroom { + will-change: transform; + transition: transform 200ms linear; +} +.headroom--pinned { + transform: translateY(0%); +} +.headroom--unpinned { + transform: translateY(-100%); +} + +/* mark.js ----------------------------*/ + +mark { + background-color: rgba(255, 255, 51, 0.5); + border-bottom: 2px solid rgba(255, 153, 51, 0.3); + padding: 1px; +} + +/* vertical spacing after htmlwidgets */ +.html-widget { + margin-bottom: 10px; +} + +/* fontawesome ------------------------ */ + +.fab { + font-family: "Font Awesome 5 Brands" !important; +} + +/* don't display links in code chunks when printing */ +/* source: https://stackoverflow.com/a/10781533 */ +@media print { + code a:link:after, code a:visited:after { + content: ""; + } +} + +/* Section anchors --------------------------------- + Added in pandoc 2.11: https://github.com/jgm/pandoc-templates/commit/9904bf71 +*/ + +div.csl-bib-body { } +div.csl-entry { + clear: both; +} +.hanging-indent div.csl-entry { + margin-left:2em; + text-indent:-2em; +} +div.csl-left-margin { + min-width:2em; + float:left; +} +div.csl-right-inline { + margin-left:2em; + padding-left:1em; +} +div.csl-indent { + margin-left: 2em; +} diff --git a/docs/pkgdown.js b/docs/pkgdown.js new file mode 100644 index 0000000..6f0eee4 --- /dev/null +++ b/docs/pkgdown.js @@ -0,0 +1,108 @@ +/* http://gregfranko.com/blog/jquery-best-practices/ */ +(function($) { + $(function() { + + $('.navbar-fixed-top').headroom(); + + $('body').css('padding-top', $('.navbar').height() + 10); + $(window).resize(function(){ + $('body').css('padding-top', $('.navbar').height() + 10); + }); + + $('[data-toggle="tooltip"]').tooltip(); + + var cur_path = paths(location.pathname); + var links = $("#navbar ul li a"); + var max_length = -1; + var pos = -1; + for (var i = 0; i < links.length; i++) { + if (links[i].getAttribute("href") === "#") + continue; + // Ignore external links + if (links[i].host !== location.host) + continue; + + var nav_path = paths(links[i].pathname); + + var length = prefix_length(nav_path, cur_path); + if (length > max_length) { + max_length = length; + pos = i; + } + } + + // Add class to parent
  • , and enclosing
  • if in dropdown + if (pos >= 0) { + var menu_anchor = $(links[pos]); + menu_anchor.parent().addClass("active"); + menu_anchor.closest("li.dropdown").addClass("active"); + } + }); + + function paths(pathname) { + var pieces = pathname.split("/"); + pieces.shift(); // always starts with / + + var end = pieces[pieces.length - 1]; + if (end === "index.html" || end === "") + pieces.pop(); + return(pieces); + } + + // Returns -1 if not found + function prefix_length(needle, haystack) { + if (needle.length > haystack.length) + return(-1); + + // Special case for length-0 haystack, since for loop won't run + if (haystack.length === 0) { + return(needle.length === 0 ? 0 : -1); + } + + for (var i = 0; i < haystack.length; i++) { + if (needle[i] != haystack[i]) + return(i); + } + + return(haystack.length); + } + + /* Clipboard --------------------------*/ + + function changeTooltipMessage(element, msg) { + var tooltipOriginalTitle=element.getAttribute('data-original-title'); + element.setAttribute('data-original-title', msg); + $(element).tooltip('show'); + element.setAttribute('data-original-title', tooltipOriginalTitle); + } + + if(ClipboardJS.isSupported()) { + $(document).ready(function() { + var copyButton = ""; + + $("div.sourceCode").addClass("hasCopyButton"); + + // Insert copy buttons: + $(copyButton).prependTo(".hasCopyButton"); + + // Initialize tooltips: + $('.btn-copy-ex').tooltip({container: 'body'}); + + // Initialize clipboard: + var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { + text: function(trigger) { + return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); + } + }); + + clipboardBtnCopies.on('success', function(e) { + changeTooltipMessage(e.trigger, 'Copied!'); + e.clearSelection(); + }); + + clipboardBtnCopies.on('error', function() { + changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); + }); + }); + } +})(window.jQuery || window.$) diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml new file mode 100644 index 0000000..ad79941 --- /dev/null +++ b/docs/pkgdown.yml @@ -0,0 +1,7 @@ +pandoc: 2.11.4 +pkgdown: 2.0.2 +pkgdown_sha: ~ +articles: + a01_overview: a01_overview.html +last_built: 2022-09-19T22:38Z + diff --git a/docs/reference/Rplot001.png b/docs/reference/Rplot001.png new file mode 100644 index 0000000..17a3580 Binary files /dev/null and b/docs/reference/Rplot001.png differ diff --git a/docs/reference/dlm_trends.html b/docs/reference/dlm_trends.html new file mode 100644 index 0000000..45db700 --- /dev/null +++ b/docs/reference/dlm_trends.html @@ -0,0 +1,128 @@ + +Summarize and plot time varying coefficients from the fitted model — dlm_trends • mvdlm + + +
    +
    + + + +
    +
    + + +
    +

    Summarize and plot time varying coefficients from the fitted model

    +
    + +
    +
    dlm_trends(fitted_model)
    +
    + +
    +

    Arguments

    +
    fitted_model
    +

    A fitted model object

    +
    +
    +

    Value

    +

    A list containing the plot and data used +to fit the model. These include plot and b_varying

    +
    + +
    +

    Examples

    +
    # \donttest{
    +set.seed(123)
    +N = 20
    +data = data.frame("y" = runif(N),
    +                  "cov1" = rnorm(N),
    +                  "cov2" = rnorm(N),
    +                  "year" = 1:N,
    +                  "season" = sample(c("A","B"), size=N, replace=T))
    +b_1 = cumsum(rnorm(N))
    +b_2 = cumsum(rnorm(N))
    +data$y = data$cov1*b_1 + data$cov2*b_2
    +time_varying = y ~ cov1 + cov2
    +formula = NULL
    +fit <- fit_dlm(formula = formula,
    +               time_varying = time_varying,
    +               time = "year",
    +               est_df = FALSE,
    +               family = c("normal"),
    +               data, chains = 1, iter = 20)
    +#> Error in data$`(Intercept)` <- 1: object of type 'symbol' is not subsettable
    +dlm_trends(fit)
    +#> Error in broom.mixed::tidy(fitted_model$fit): object 'fit' not found
    +# }
    +
    +
    +
    +
    + +
    + + +
    + +
    +

    Site built with pkgdown 2.0.2.

    +
    + +
    + + + + + + + + diff --git a/docs/reference/fit_dlm.html b/docs/reference/fit_dlm.html new file mode 100644 index 0000000..761c11e --- /dev/null +++ b/docs/reference/fit_dlm.html @@ -0,0 +1,189 @@ + +Fit a Bayesian Dirichlet regression model, allowing for zero-and-one inflation, covariates, and overdispersion — fit_dlm • mvdlm + + +
    +
    + + + +
    +
    + + +
    +

    Fit a Bayesian Dirichlet regression model that optionally includes covariates to estimate +effects of factor or continuous variables on proportions.

    +
    + +
    +
    fit_dlm(
    +  formula = NULL,
    +  time_varying = NULL,
    +  time = "year",
    +  est_df = FALSE,
    +  family = c("normal", "binomial", "poisson", "nbinom2", "gamma", "lognormal"),
    +  correlated_rw = TRUE,
    +  data,
    +  chains = 3,
    +  iter = 2000,
    +  warmup = floor(iter/2),
    +  ...
    +)
    +
    + +
    +

    Arguments

    +
    formula
    +

    The model formula for the fixed effects; at least this formula or time_varying needs to have the response included

    +
    time_varying
    +

    The model formula for the time-varying effects; at least this formula or formula needs to have the response included

    +
    time
    +

    String describing the name of the variable corresponding to time, defaults to "year"

    +
    est_df
    +

    Whether or not to estimate deviaitions of B as Student - t with estimated degrees of freedom, defaults to FALSE

    +
    family,
    +

    The name of the family used for the response; can be one of "normal","binomial","possion","nbinom2","gamma","lognormal"

    +
    correlated_rw,
    +

    Whether to estimate time-varying parameters as correlated random walk, defaults to TRUE

    +
    data
    +

    The data frame including response and covariates for all model components

    +
    chains
    +

    Number of mcmc chains, defaults to 3

    +
    iter
    +

    Number of mcmc iterations, defaults to 2000

    +
    warmup
    +

    Number iterations for mcmc warmup, defaults to 1/2 of the iterations

    +
    ...
    +

    Any other arguments to pass to rstan::sampling().

    +
    +
    +

    Value

    +

    A list containing the fitted model and arguments and data used +to fit the model. These include model (the fitted model object of class stanfit),

    +
    + +
    +

    Examples

    +
    # \donttest{
    +set.seed(123)
    +N = 20
    +data = data.frame("y" = runif(N),
    +                  "cov1" = rnorm(N),
    +                  "cov2" = rnorm(N),
    +                  "year" = 1:N,
    +                  "season" = sample(c("A","B"), size=N, replace=TRUE))
    +b_1 = cumsum(rnorm(N))
    +b_2 = cumsum(rnorm(N))
    +data$y = data$cov1*b_1 + data$cov2*b_2
    +time_varying = y ~ cov1 + cov2
    +formula = NULL
    +
    +# fit a model with a time varying component
    +fit <- fit_dlm(formula = formula,
    +               time_varying = time_varying,
    +               time = "year",
    +               est_df = FALSE,
    +               family = c("normal"),
    +               data, chains = 1, iter = 20)
    +#> Error in data$`(Intercept)` <- 1: object of type 'symbol' is not subsettable
    +
    +# fit a model with a time varying and fixed component (here, fixed intercept)
    +fit <- fit_dlm(formula = y ~ 1,
    +               time_varying = y ~ -1 + cov1 + cov2,
    +               time = "year",
    +               est_df = FALSE,
    +               family = c("normal"),
    +               data, chains = 1, iter = 20)
    +#> Error in data$`(Intercept)` <- 1: object of type 'symbol' is not subsettable
    +
    +#' # fit a model with deviations modeled with a multivariate Student-t
    +fit <- fit_dlm(formula = y ~ 1,
    +               time_varying = y ~ -1 + cov1 + cov2,
    +               time = "year",
    +               est_df = TRUE,
    +               family = c("normal"),
    +               data, chains = 1, iter = 20)
    +#> Error in data$`(Intercept)` <- 1: object of type 'symbol' is not subsettable
    +
    +#' #' # fit a model with deviations modeled with a multivariate Student-t
    +fit <- fit_dlm(formula = y ~ 1,
    +               time_varying = y ~ -1 + cov1 + cov2,
    +               time = "year",
    +               est_df = TRUE,
    +               family = c("normal"),
    +               data, chains = 1, iter = 20)
    +#> Error in data$`(Intercept)` <- 1: object of type 'symbol' is not subsettable
    +# }
    +
    +
    +
    +
    + +
    + + +
    + +
    +

    Site built with pkgdown 2.0.2.

    +
    + +
    + + + + + + + + diff --git a/docs/reference/index.html b/docs/reference/index.html new file mode 100644 index 0000000..098089f --- /dev/null +++ b/docs/reference/index.html @@ -0,0 +1,96 @@ + +Function reference • mvdlm + + +
    +
    + + + +
    +
    + + + + + + + + + +
    +

    All functions

    +

    +
    +

    dlm_trends()

    +

    Summarize and plot time varying coefficients from the fitted model

    +

    fit_dlm()

    +

    Fit a Bayesian Dirichlet regression model, allowing for zero-and-one inflation, covariates, and overdispersion

    +

    mvdlm-package

    +

    The 'mvdlm' package.

    + + +
    + + +
    + +
    +

    Site built with pkgdown 2.0.2.

    +
    + +
    + + + + + + + + diff --git a/docs/reference/mvdlm-package.html b/docs/reference/mvdlm-package.html new file mode 100644 index 0000000..f4133b3 --- /dev/null +++ b/docs/reference/mvdlm-package.html @@ -0,0 +1,91 @@ + +The 'mvdlm' package. — mvdlm-package • mvdlm + + +
    +
    + + + +
    +
    + + +
    +

    A DESCRIPTION OF THE PACKAGE

    +
    + + +
    +

    References

    +

    Stan Development Team (2020). RStan: the R interface to Stan. R package version 2.21.2. https://mc-stan.org

    +
    + +
    + +
    + + +
    + +
    +

    Site built with pkgdown 2.0.2.

    +
    + +
    + + + + + + + + diff --git a/docs/sitemap.xml b/docs/sitemap.xml new file mode 100644 index 0000000..1520355 --- /dev/null +++ b/docs/sitemap.xml @@ -0,0 +1,30 @@ + + + + /404.html + + + /articles/a01_overview.html + + + /articles/index.html + + + /authors.html + + + /index.html + + + /reference/dlm_trends.html + + + /reference/fit_dlm.html + + + /reference/index.html + + + /reference/mvdlm-package.html + + diff --git a/inst/include/stan_meta_header.hpp b/inst/include/stan_meta_header.hpp new file mode 100644 index 0000000..3b914da --- /dev/null +++ b/inst/include/stan_meta_header.hpp @@ -0,0 +1 @@ +// Insert all #include statements here diff --git a/inst/stan/dlm.stan b/inst/stan/dlm.stan new file mode 100644 index 0000000..9c4113a --- /dev/null +++ b/inst/stan/dlm.stan @@ -0,0 +1,161 @@ +data { + int N; // number of samples + int nT; // number of time steps + real y[N]; // observations + int y_int[N]; // observations + int fixed_N; + int n_fixed_covars; // number fixed covariates + int fixed_time_indx[fixed_N]; // time index of fixed effects + int fixed_var_indx[fixed_N]; // variable index of fixed effects + real fixed_x_value[fixed_N]; // value of covariates + int varying_N; + int n_varying_covars; // number fixed covariates + int varying_time_indx[varying_N]; // time index of fixed effects + int varying_var_indx[varying_N]; // variable index of fixed effects + real varying_x_value[varying_N]; // value of covariates + int est_df; // whether to estimate Student - t df + int family; + int n_fixed_NAs; + int fixed_NAs[n_fixed_NAs + 2]; + int n_varying_NAs; + int varying_NAs[n_varying_NAs + 2]; + int correlated_rw; +} +transformed data { + vector[n_varying_covars] zeros; + for(i in 1:n_varying_covars) zeros[i] = 0; +} +parameters { + vector[n_fixed_covars] b_fixed; + vector[n_varying_covars] b_devs0; + vector[n_varying_covars] b_devs[nT-1]; + cholesky_factor_corr[n_varying_covars * correlated_rw] Lcorr; // cholesky factor (L_u matrix for R) + vector[n_varying_covars] sigma; + vector[1] phi; + vector[est_df] nu; + vector[n_fixed_NAs] missing_fixed; + vector[n_varying_NAs] missing_varying; +} +transformed parameters { + vector[n_varying_covars] b_varying[nT]; + //corr_matrix[n_varying_covars * correlated_rw] R; // correlation matrix + //cov_matrix[n_varying_covars * correlated_rw] Sigma; // VCV matrix derived + matrix[n_varying_covars * correlated_rw, n_varying_covars * correlated_rw] R; + matrix[n_varying_covars * correlated_rw, n_varying_covars * correlated_rw] Sigma; + vector[nT] eta; // linear predictor on link scale + matrix[nT, n_fixed_covars] X_fixed; + matrix[nT, n_varying_covars] X_varying; + + // covariance matrix stuff + if(correlated_rw == 1) { + R = multiply_lower_tri_self_transpose(Lcorr); // R = Lcorr * Lcorr' + Sigma = quad_form_diag(R, sigma); // quad_form_diag: diag_matrix(sig) * R * diag_matrix(sig) + } + + // re-assemble X matrices for fixed and time-varying effects + if(n_fixed_covars > 0) { + for(i in 1:fixed_N) { + X_fixed[fixed_time_indx[i], fixed_var_indx[i]] = fixed_x_value[i]; + } + // add in missing vals + for(i in 1:n_fixed_NAs) { + X_fixed[fixed_time_indx[fixed_NAs[i]], fixed_var_indx[fixed_NAs[i]]] = missing_fixed[i]; + } + } + if(n_varying_covars > 0) { + for(i in 1:varying_N) { + X_varying[varying_time_indx[i], varying_var_indx[i]] = varying_x_value[i]; + } + // add in missing vals + for(i in 1:n_varying_NAs) { + X_varying[varying_time_indx[varying_NAs[i]], varying_var_indx[varying_NAs[i]]] = missing_varying[i]; + } + } + + // time - varying coefficients + b_varying[1] = b_devs0; + for(t in 2:nT) { + b_varying[t] = b_varying[t-1] + b_devs[t-1]; + } + + // calculate predictions (eta) + for(t in 1:nT) eta[t] = 0; + if(n_fixed_covars > 0) eta = eta + X_fixed * b_fixed; + if(n_varying_covars > 0) { + for(t in 1:nT) { + eta[t] = eta[t] + X_varying[t] * b_varying[t]; + } + } +} +model { + sigma ~ cauchy(0, 5); // prior for sigma + Lcorr ~ lkj_corr_cholesky(2.0); // prior for cholesky factor of a correlation matrix + phi ~ student_t(3,0,2); // obseervation variance + b_fixed ~ normal(0,1); + nu ~ student_t(3,0,2); + + missing_fixed ~ normal(0,1); // estimates of missing Xs for fixed model + missing_varying ~ normal(0,1); // estimates of missing Xs for time varying model + b_devs0 ~ normal(0,1); // initial values of B at time t + if(est_df == 0) { + if(correlated_rw == 1) { + for(t in 1:(nT-1)) { + b_devs[t] ~ multi_normal(zeros, Sigma); + } + } else { + for(t in 1:(nT-1)) { + b_devs[t] ~ normal(zeros, sigma); + } + } + } else { + if(correlated_rw == 1) { + for(t in 1:(nT-1)) { + b_devs[t] ~ multi_student_t(nu[1], zeros, Sigma); + } + } else { + for(t in 1:(nT-1)) { + b_devs[t] ~ student_t(nu[1], zeros, sigma); + } + } + } + + if(family==1) { + y ~ normal(eta, phi[1]); // Gaussian + } + if(family==2) { + y_int ~ bernoulli_logit(eta); // binomial + } + if(family==3) { + y_int ~ poisson_log(eta); // Poisson + } + if(family==4) { + y_int ~ neg_binomial_2_log(eta, phi[1]); // NegBin2 + } + if(family==5) { + y ~ gamma(phi[1], phi[1] ./ exp(eta)); // Gamma + } + if(family==6) { + y ~ lognormal(eta, phi[1]); // Lognormal + } +} +generated quantities { + vector[N] log_lik; + if(family==1) { + for (n in 1:N) log_lik[n] = normal_lpdf(y[n] | eta[n], phi[1]); // Gaussian + } + if(family==2) { + for (n in 1:N) log_lik[n] = bernoulli_lpmf(y_int[n] | inv_logit(eta[n])); // binomial + } + if(family==3) { + for (n in 1:N) log_lik[n] = poisson_lpmf(y_int[n] | exp(eta[n])); // Poisson + } + if(family==4) { + for (n in 1:N) log_lik[n] = normal_lpdf(y[n] | eta[n], phi[1]); // NegBin2 + } + if(family==5) { + for (n in 1:N) log_lik[n] = gamma_lpdf(y[n] | phi[1], phi[1] ./ exp(eta[n])); // Gamma + } + if(family==6) { + for (n in 1:N) log_lik[n] = lognormal_lpdf(y[n] | eta[n], phi[1]); // Lognormal + } +} diff --git a/inst/stan/include/license.stan b/inst/stan/include/license.stan new file mode 100644 index 0000000..d531281 --- /dev/null +++ b/inst/stan/include/license.stan @@ -0,0 +1,14 @@ +/* + zoid is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + zoid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with zoid. If not, see . +*/ diff --git a/man/dlm_trends.Rd b/man/dlm_trends.Rd new file mode 100644 index 0000000..b526818 --- /dev/null +++ b/man/dlm_trends.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dlm_trends.R +\name{dlm_trends} +\alias{dlm_trends} +\title{Summarize and plot time varying coefficients from the fitted model} +\usage{ +dlm_trends(fitted_model) +} +\arguments{ +\item{fitted_model}{A fitted model object} +} +\value{ +A list containing the plot and data used +to fit the model. These include \code{plot} and \code{b_varying} +} +\description{ +Summarize and plot time varying coefficients from the fitted model +} +\examples{ +\donttest{ +set.seed(123) +N = 20 +data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=T)) +b_1 = cumsum(rnorm(N)) +b_2 = cumsum(rnorm(N)) +data$y = data$cov1*b_1 + data$cov2*b_2 +time_varying = y ~ cov1 + cov2 +formula = NULL +fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = FALSE, + family = c("normal"), + data, chains = 1, iter = 20) +dlm_trends(fit) +} + +} diff --git a/man/fit_dlm.Rd b/man/fit_dlm.Rd new file mode 100644 index 0000000..26df1db --- /dev/null +++ b/man/fit_dlm.Rd @@ -0,0 +1,100 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fitting.R +\name{fit_dlm} +\alias{fit_dlm} +\title{Fit a Bayesian Dirichlet regression model, allowing for zero-and-one inflation, covariates, and overdispersion} +\usage{ +fit_dlm( + formula = NULL, + time_varying = NULL, + time = "year", + est_df = FALSE, + family = c("normal", "binomial", "poisson", "nbinom2", "gamma", "lognormal"), + correlated_rw = TRUE, + data, + chains = 3, + iter = 2000, + warmup = floor(iter/2), + ... +) +} +\arguments{ +\item{formula}{The model formula for the fixed effects; at least this formula or \code{time_varying} needs to have the response included} + +\item{time_varying}{The model formula for the time-varying effects; at least this formula or \code{formula} needs to have the response included} + +\item{time}{String describing the name of the variable corresponding to time, defaults to "year"} + +\item{est_df}{Whether or not to estimate deviaitions of B as Student - t with estimated degrees of freedom, defaults to \code{FALSE}} + +\item{family, }{The name of the family used for the response; can be one of "normal","binomial","possion","nbinom2","gamma","lognormal"} + +\item{correlated_rw, }{Whether to estimate time-varying parameters as correlated random walk, defaults to TRUE} + +\item{data}{The data frame including response and covariates for all model components} + +\item{chains}{Number of mcmc chains, defaults to 3} + +\item{iter}{Number of mcmc iterations, defaults to 2000} + +\item{warmup}{Number iterations for mcmc warmup, defaults to 1/2 of the iterations} + +\item{...}{Any other arguments to pass to \code{\link[rstan:stanmodel-method-sampling]{rstan::sampling()}}.} +} +\value{ +A list containing the fitted model and arguments and data used +to fit the model. These include \code{model} (the fitted model object of class \code{stanfit}), +} +\description{ +Fit a Bayesian Dirichlet regression model that optionally includes covariates to estimate +effects of factor or continuous variables on proportions. +} +\examples{ +\donttest{ +set.seed(123) +N = 20 +data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=TRUE)) +b_1 = cumsum(rnorm(N)) +b_2 = cumsum(rnorm(N)) +data$y = data$cov1*b_1 + data$cov2*b_2 +time_varying = y ~ cov1 + cov2 +formula = NULL + +# fit a model with a time varying component +fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = FALSE, + family = c("normal"), + data, chains = 1, iter = 20) + +# fit a model with a time varying and fixed component (here, fixed intercept) +fit <- fit_dlm(formula = y ~ 1, + time_varying = y ~ -1 + cov1 + cov2, + time = "year", + est_df = FALSE, + family = c("normal"), + data, chains = 1, iter = 20) + +#' # fit a model with deviations modeled with a multivariate Student-t +fit <- fit_dlm(formula = y ~ 1, + time_varying = y ~ -1 + cov1 + cov2, + time = "year", + est_df = TRUE, + family = c("normal"), + data, chains = 1, iter = 20) + +#' #' # fit a model with deviations modeled with a multivariate Student-t +fit <- fit_dlm(formula = y ~ 1, + time_varying = y ~ -1 + cov1 + cov2, + time = "year", + est_df = TRUE, + family = c("normal"), + data, chains = 1, iter = 20) +} + +} diff --git a/man/mvdlm-package.Rd b/man/mvdlm-package.Rd new file mode 100644 index 0000000..a8da76e --- /dev/null +++ b/man/mvdlm-package.Rd @@ -0,0 +1,13 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mvdlm-package.R +\docType{package} +\name{mvdlm-package} +\alias{mvdlm-package} +\alias{mvdlm} +\title{The 'mvdlm' package.} +\description{ +A DESCRIPTION OF THE PACKAGE +} +\references{ +Stan Development Team (2020). RStan: the R interface to Stan. R package version 2.21.2. https://mc-stan.org +} diff --git a/src/Makevars b/src/Makevars new file mode 100644 index 0000000..bcc8a7c --- /dev/null +++ b/src/Makevars @@ -0,0 +1,9 @@ +# Generated by rstantools. Do not edit by hand. + +STANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders") + +PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error +PKG_CXXFLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::CxxFlags()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::CxxFlags()") +PKG_LIBS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::RcppParallelLibs()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::LdFlags()") + +CXX_STD = CXX14 diff --git a/src/Makevars.win b/src/Makevars.win new file mode 100644 index 0000000..60f0bdd --- /dev/null +++ b/src/Makevars.win @@ -0,0 +1,9 @@ +# Generated by rstantools. Do not edit by hand. + +STANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders") + +PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DRCPP_PARALLEL_USE_TBB=1 +PKG_CXXFLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::CxxFlags()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::CxxFlags()") +PKG_LIBS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::RcppParallelLibs()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::LdFlags()") + +CXX_STD = CXX14 diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp new file mode 100644 index 0000000..af7c576 --- /dev/null +++ b/src/RcppExports.cpp @@ -0,0 +1,25 @@ +// Generated by using Rcpp::compileAttributes() -> do not edit by hand +// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 + +#include +#include + +using namespace Rcpp; + +#ifdef RCPP_USE_GLOBAL_ROSTREAM +Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); +Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); +#endif + + +RcppExport SEXP _rcpp_module_boot_stan_fit4dlm_mod(); + +static const R_CallMethodDef CallEntries[] = { + {"_rcpp_module_boot_stan_fit4dlm_mod", (DL_FUNC) &_rcpp_module_boot_stan_fit4dlm_mod, 0}, + {NULL, NULL, 0} +}; + +RcppExport void R_init_mvdlm(DllInfo *dll) { + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + R_useDynamicSymbols(dll, FALSE); +} diff --git a/src/stanExports_dlm.cc b/src/stanExports_dlm.cc new file mode 100644 index 0000000..a98f7ad --- /dev/null +++ b/src/stanExports_dlm.cc @@ -0,0 +1,32 @@ +// Generated by rstantools. Do not edit by hand. + +#include +using namespace Rcpp ; +#include "stanExports_dlm.h" + +RCPP_MODULE(stan_fit4dlm_mod) { + + + class_ >("model_dlm") + + .constructor() + + + .method("call_sampler", &rstan::stan_fit ::call_sampler) + .method("param_names", &rstan::stan_fit ::param_names) + .method("param_names_oi", &rstan::stan_fit ::param_names_oi) + .method("param_fnames_oi", &rstan::stan_fit ::param_fnames_oi) + .method("param_dims", &rstan::stan_fit ::param_dims) + .method("param_dims_oi", &rstan::stan_fit ::param_dims_oi) + .method("update_param_oi", &rstan::stan_fit ::update_param_oi) + .method("param_oi_tidx", &rstan::stan_fit ::param_oi_tidx) + .method("grad_log_prob", &rstan::stan_fit ::grad_log_prob) + .method("log_prob", &rstan::stan_fit ::log_prob) + .method("unconstrain_pars", &rstan::stan_fit ::unconstrain_pars) + .method("constrain_pars", &rstan::stan_fit ::constrain_pars) + .method("num_pars_unconstrained", &rstan::stan_fit ::num_pars_unconstrained) + .method("unconstrained_param_names", &rstan::stan_fit ::unconstrained_param_names) + .method("constrained_param_names", &rstan::stan_fit ::constrained_param_names) + .method("standalone_gqs", &rstan::stan_fit ::standalone_gqs) + ; +} diff --git a/src/stanExports_dlm.h b/src/stanExports_dlm.h new file mode 100644 index 0000000..1b4015f --- /dev/null +++ b/src/stanExports_dlm.h @@ -0,0 +1,1555 @@ +// Generated by rstantools. Do not edit by hand. + +/* + zoid is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + zoid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with zoid. If not, see . +*/ +#ifndef MODELS_HPP +#define MODELS_HPP +#define STAN__SERVICES__COMMAND_HPP +#include +// Code generated by Stan version 2.21.0 +#include +namespace model_dlm_namespace { +using std::istream; +using std::string; +using std::stringstream; +using std::vector; +using stan::io::dump; +using stan::math::lgamma; +using stan::model::prob_grad; +using namespace stan::math; +static int current_statement_begin__; +stan::io::program_reader prog_reader__() { + stan::io::program_reader reader; + reader.add_event(0, 0, "start", "model_dlm"); + reader.add_event(163, 161, "end", "model_dlm"); + return reader; +} +#include +class model_dlm + : public stan::model::model_base_crtp { +private: + int N; + int nT; + std::vector y; + std::vector y_int; + int fixed_N; + int n_fixed_covars; + std::vector fixed_time_indx; + std::vector fixed_var_indx; + std::vector fixed_x_value; + int varying_N; + int n_varying_covars; + std::vector varying_time_indx; + std::vector varying_var_indx; + std::vector varying_x_value; + int est_df; + int family; + int n_fixed_NAs; + std::vector fixed_NAs; + int n_varying_NAs; + std::vector varying_NAs; + int correlated_rw; + vector_d zeros; +public: + model_dlm(stan::io::var_context& context__, + std::ostream* pstream__ = 0) + : model_base_crtp(0) { + ctor_body(context__, 0, pstream__); + } + model_dlm(stan::io::var_context& context__, + unsigned int random_seed__, + std::ostream* pstream__ = 0) + : model_base_crtp(0) { + ctor_body(context__, random_seed__, pstream__); + } + void ctor_body(stan::io::var_context& context__, + unsigned int random_seed__, + std::ostream* pstream__) { + typedef double local_scalar_t__; + boost::ecuyer1988 base_rng__ = + stan::services::util::create_rng(random_seed__, 0); + (void) base_rng__; // suppress unused var warning + current_statement_begin__ = -1; + static const char* function__ = "model_dlm_namespace::model_dlm"; + (void) function__; // dummy to suppress unused var warning + size_t pos__; + (void) pos__; // dummy to suppress unused var warning + std::vector vals_i__; + std::vector vals_r__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + (void) DUMMY_VAR__; // suppress unused var warning + try { + // initialize data block variables from context__ + current_statement_begin__ = 2; + context__.validate_dims("data initialization", "N", "int", context__.to_vec()); + N = int(0); + vals_i__ = context__.vals_i("N"); + pos__ = 0; + N = vals_i__[pos__++]; + current_statement_begin__ = 3; + context__.validate_dims("data initialization", "nT", "int", context__.to_vec()); + nT = int(0); + vals_i__ = context__.vals_i("nT"); + pos__ = 0; + nT = vals_i__[pos__++]; + current_statement_begin__ = 4; + validate_non_negative_index("y", "N", N); + context__.validate_dims("data initialization", "y", "double", context__.to_vec(N)); + y = std::vector(N, double(0)); + vals_r__ = context__.vals_r("y"); + pos__ = 0; + size_t y_k_0_max__ = N; + for (size_t k_0__ = 0; k_0__ < y_k_0_max__; ++k_0__) { + y[k_0__] = vals_r__[pos__++]; + } + current_statement_begin__ = 5; + validate_non_negative_index("y_int", "N", N); + context__.validate_dims("data initialization", "y_int", "int", context__.to_vec(N)); + y_int = std::vector(N, int(0)); + vals_i__ = context__.vals_i("y_int"); + pos__ = 0; + size_t y_int_k_0_max__ = N; + for (size_t k_0__ = 0; k_0__ < y_int_k_0_max__; ++k_0__) { + y_int[k_0__] = vals_i__[pos__++]; + } + current_statement_begin__ = 6; + context__.validate_dims("data initialization", "fixed_N", "int", context__.to_vec()); + fixed_N = int(0); + vals_i__ = context__.vals_i("fixed_N"); + pos__ = 0; + fixed_N = vals_i__[pos__++]; + current_statement_begin__ = 7; + context__.validate_dims("data initialization", "n_fixed_covars", "int", context__.to_vec()); + n_fixed_covars = int(0); + vals_i__ = context__.vals_i("n_fixed_covars"); + pos__ = 0; + n_fixed_covars = vals_i__[pos__++]; + current_statement_begin__ = 8; + validate_non_negative_index("fixed_time_indx", "fixed_N", fixed_N); + context__.validate_dims("data initialization", "fixed_time_indx", "int", context__.to_vec(fixed_N)); + fixed_time_indx = std::vector(fixed_N, int(0)); + vals_i__ = context__.vals_i("fixed_time_indx"); + pos__ = 0; + size_t fixed_time_indx_k_0_max__ = fixed_N; + for (size_t k_0__ = 0; k_0__ < fixed_time_indx_k_0_max__; ++k_0__) { + fixed_time_indx[k_0__] = vals_i__[pos__++]; + } + current_statement_begin__ = 9; + validate_non_negative_index("fixed_var_indx", "fixed_N", fixed_N); + context__.validate_dims("data initialization", "fixed_var_indx", "int", context__.to_vec(fixed_N)); + fixed_var_indx = std::vector(fixed_N, int(0)); + vals_i__ = context__.vals_i("fixed_var_indx"); + pos__ = 0; + size_t fixed_var_indx_k_0_max__ = fixed_N; + for (size_t k_0__ = 0; k_0__ < fixed_var_indx_k_0_max__; ++k_0__) { + fixed_var_indx[k_0__] = vals_i__[pos__++]; + } + current_statement_begin__ = 10; + validate_non_negative_index("fixed_x_value", "fixed_N", fixed_N); + context__.validate_dims("data initialization", "fixed_x_value", "double", context__.to_vec(fixed_N)); + fixed_x_value = std::vector(fixed_N, double(0)); + vals_r__ = context__.vals_r("fixed_x_value"); + pos__ = 0; + size_t fixed_x_value_k_0_max__ = fixed_N; + for (size_t k_0__ = 0; k_0__ < fixed_x_value_k_0_max__; ++k_0__) { + fixed_x_value[k_0__] = vals_r__[pos__++]; + } + current_statement_begin__ = 11; + context__.validate_dims("data initialization", "varying_N", "int", context__.to_vec()); + varying_N = int(0); + vals_i__ = context__.vals_i("varying_N"); + pos__ = 0; + varying_N = vals_i__[pos__++]; + current_statement_begin__ = 12; + context__.validate_dims("data initialization", "n_varying_covars", "int", context__.to_vec()); + n_varying_covars = int(0); + vals_i__ = context__.vals_i("n_varying_covars"); + pos__ = 0; + n_varying_covars = vals_i__[pos__++]; + current_statement_begin__ = 13; + validate_non_negative_index("varying_time_indx", "varying_N", varying_N); + context__.validate_dims("data initialization", "varying_time_indx", "int", context__.to_vec(varying_N)); + varying_time_indx = std::vector(varying_N, int(0)); + vals_i__ = context__.vals_i("varying_time_indx"); + pos__ = 0; + size_t varying_time_indx_k_0_max__ = varying_N; + for (size_t k_0__ = 0; k_0__ < varying_time_indx_k_0_max__; ++k_0__) { + varying_time_indx[k_0__] = vals_i__[pos__++]; + } + current_statement_begin__ = 14; + validate_non_negative_index("varying_var_indx", "varying_N", varying_N); + context__.validate_dims("data initialization", "varying_var_indx", "int", context__.to_vec(varying_N)); + varying_var_indx = std::vector(varying_N, int(0)); + vals_i__ = context__.vals_i("varying_var_indx"); + pos__ = 0; + size_t varying_var_indx_k_0_max__ = varying_N; + for (size_t k_0__ = 0; k_0__ < varying_var_indx_k_0_max__; ++k_0__) { + varying_var_indx[k_0__] = vals_i__[pos__++]; + } + current_statement_begin__ = 15; + validate_non_negative_index("varying_x_value", "varying_N", varying_N); + context__.validate_dims("data initialization", "varying_x_value", "double", context__.to_vec(varying_N)); + varying_x_value = std::vector(varying_N, double(0)); + vals_r__ = context__.vals_r("varying_x_value"); + pos__ = 0; + size_t varying_x_value_k_0_max__ = varying_N; + for (size_t k_0__ = 0; k_0__ < varying_x_value_k_0_max__; ++k_0__) { + varying_x_value[k_0__] = vals_r__[pos__++]; + } + current_statement_begin__ = 16; + context__.validate_dims("data initialization", "est_df", "int", context__.to_vec()); + est_df = int(0); + vals_i__ = context__.vals_i("est_df"); + pos__ = 0; + est_df = vals_i__[pos__++]; + current_statement_begin__ = 17; + context__.validate_dims("data initialization", "family", "int", context__.to_vec()); + family = int(0); + vals_i__ = context__.vals_i("family"); + pos__ = 0; + family = vals_i__[pos__++]; + current_statement_begin__ = 18; + context__.validate_dims("data initialization", "n_fixed_NAs", "int", context__.to_vec()); + n_fixed_NAs = int(0); + vals_i__ = context__.vals_i("n_fixed_NAs"); + pos__ = 0; + n_fixed_NAs = vals_i__[pos__++]; + current_statement_begin__ = 19; + validate_non_negative_index("fixed_NAs", "(n_fixed_NAs + 2)", (n_fixed_NAs + 2)); + context__.validate_dims("data initialization", "fixed_NAs", "int", context__.to_vec((n_fixed_NAs + 2))); + fixed_NAs = std::vector((n_fixed_NAs + 2), int(0)); + vals_i__ = context__.vals_i("fixed_NAs"); + pos__ = 0; + size_t fixed_NAs_k_0_max__ = (n_fixed_NAs + 2); + for (size_t k_0__ = 0; k_0__ < fixed_NAs_k_0_max__; ++k_0__) { + fixed_NAs[k_0__] = vals_i__[pos__++]; + } + current_statement_begin__ = 20; + context__.validate_dims("data initialization", "n_varying_NAs", "int", context__.to_vec()); + n_varying_NAs = int(0); + vals_i__ = context__.vals_i("n_varying_NAs"); + pos__ = 0; + n_varying_NAs = vals_i__[pos__++]; + current_statement_begin__ = 21; + validate_non_negative_index("varying_NAs", "(n_varying_NAs + 2)", (n_varying_NAs + 2)); + context__.validate_dims("data initialization", "varying_NAs", "int", context__.to_vec((n_varying_NAs + 2))); + varying_NAs = std::vector((n_varying_NAs + 2), int(0)); + vals_i__ = context__.vals_i("varying_NAs"); + pos__ = 0; + size_t varying_NAs_k_0_max__ = (n_varying_NAs + 2); + for (size_t k_0__ = 0; k_0__ < varying_NAs_k_0_max__; ++k_0__) { + varying_NAs[k_0__] = vals_i__[pos__++]; + } + current_statement_begin__ = 22; + context__.validate_dims("data initialization", "correlated_rw", "int", context__.to_vec()); + correlated_rw = int(0); + vals_i__ = context__.vals_i("correlated_rw"); + pos__ = 0; + correlated_rw = vals_i__[pos__++]; + // initialize transformed data variables + current_statement_begin__ = 25; + validate_non_negative_index("zeros", "n_varying_covars", n_varying_covars); + zeros = Eigen::Matrix(n_varying_covars); + stan::math::fill(zeros, DUMMY_VAR__); + // execute transformed data statements + current_statement_begin__ = 26; + for (int i = 1; i <= n_varying_covars; ++i) { + current_statement_begin__ = 26; + stan::model::assign(zeros, + stan::model::cons_list(stan::model::index_uni(i), stan::model::nil_index_list()), + 0, + "assigning variable zeros"); + } + // validate transformed data + // validate, set parameter ranges + num_params_r__ = 0U; + param_ranges_i__.clear(); + current_statement_begin__ = 29; + validate_non_negative_index("b_fixed", "n_fixed_covars", n_fixed_covars); + num_params_r__ += n_fixed_covars; + current_statement_begin__ = 30; + validate_non_negative_index("b_devs0", "n_varying_covars", n_varying_covars); + num_params_r__ += n_varying_covars; + current_statement_begin__ = 31; + validate_non_negative_index("b_devs", "n_varying_covars", n_varying_covars); + validate_non_negative_index("b_devs", "(nT - 1)", (nT - 1)); + num_params_r__ += (n_varying_covars * (nT - 1)); + current_statement_begin__ = 32; + validate_non_negative_index("Lcorr", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + validate_non_negative_index("Lcorr", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + num_params_r__ += (((n_varying_covars * correlated_rw) * ((n_varying_covars * correlated_rw) - 1)) / 2); + current_statement_begin__ = 33; + validate_non_negative_index("sigma", "n_varying_covars", n_varying_covars); + num_params_r__ += n_varying_covars; + current_statement_begin__ = 34; + validate_non_negative_index("phi", "1", 1); + num_params_r__ += 1; + current_statement_begin__ = 35; + validate_non_negative_index("nu", "est_df", est_df); + num_params_r__ += est_df; + current_statement_begin__ = 36; + validate_non_negative_index("missing_fixed", "n_fixed_NAs", n_fixed_NAs); + num_params_r__ += n_fixed_NAs; + current_statement_begin__ = 37; + validate_non_negative_index("missing_varying", "n_varying_NAs", n_varying_NAs); + num_params_r__ += n_varying_NAs; + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); + // Next line prevents compiler griping about no return + throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); + } + } + ~model_dlm() { } + void transform_inits(const stan::io::var_context& context__, + std::vector& params_i__, + std::vector& params_r__, + std::ostream* pstream__) const { + typedef double local_scalar_t__; + stan::io::writer writer__(params_r__, params_i__); + size_t pos__; + (void) pos__; // dummy call to supress warning + std::vector vals_r__; + std::vector vals_i__; + current_statement_begin__ = 29; + if (!(context__.contains_r("b_fixed"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable b_fixed missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("b_fixed"); + pos__ = 0U; + validate_non_negative_index("b_fixed", "n_fixed_covars", n_fixed_covars); + context__.validate_dims("parameter initialization", "b_fixed", "vector_d", context__.to_vec(n_fixed_covars)); + Eigen::Matrix b_fixed(n_fixed_covars); + size_t b_fixed_j_1_max__ = n_fixed_covars; + for (size_t j_1__ = 0; j_1__ < b_fixed_j_1_max__; ++j_1__) { + b_fixed(j_1__) = vals_r__[pos__++]; + } + try { + writer__.vector_unconstrain(b_fixed); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable b_fixed: ") + e.what()), current_statement_begin__, prog_reader__()); + } + current_statement_begin__ = 30; + if (!(context__.contains_r("b_devs0"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable b_devs0 missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("b_devs0"); + pos__ = 0U; + validate_non_negative_index("b_devs0", "n_varying_covars", n_varying_covars); + context__.validate_dims("parameter initialization", "b_devs0", "vector_d", context__.to_vec(n_varying_covars)); + Eigen::Matrix b_devs0(n_varying_covars); + size_t b_devs0_j_1_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < b_devs0_j_1_max__; ++j_1__) { + b_devs0(j_1__) = vals_r__[pos__++]; + } + try { + writer__.vector_unconstrain(b_devs0); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable b_devs0: ") + e.what()), current_statement_begin__, prog_reader__()); + } + current_statement_begin__ = 31; + if (!(context__.contains_r("b_devs"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable b_devs missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("b_devs"); + pos__ = 0U; + validate_non_negative_index("b_devs", "n_varying_covars", n_varying_covars); + validate_non_negative_index("b_devs", "(nT - 1)", (nT - 1)); + context__.validate_dims("parameter initialization", "b_devs", "vector_d", context__.to_vec((nT - 1),n_varying_covars)); + std::vector > b_devs((nT - 1), Eigen::Matrix(n_varying_covars)); + size_t b_devs_j_1_max__ = n_varying_covars; + size_t b_devs_k_0_max__ = (nT - 1); + for (size_t j_1__ = 0; j_1__ < b_devs_j_1_max__; ++j_1__) { + for (size_t k_0__ = 0; k_0__ < b_devs_k_0_max__; ++k_0__) { + b_devs[k_0__](j_1__) = vals_r__[pos__++]; + } + } + size_t b_devs_i_0_max__ = (nT - 1); + for (size_t i_0__ = 0; i_0__ < b_devs_i_0_max__; ++i_0__) { + try { + writer__.vector_unconstrain(b_devs[i_0__]); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable b_devs: ") + e.what()), current_statement_begin__, prog_reader__()); + } + } + current_statement_begin__ = 32; + if (!(context__.contains_r("Lcorr"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable Lcorr missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("Lcorr"); + pos__ = 0U; + validate_non_negative_index("Lcorr", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + validate_non_negative_index("Lcorr", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + context__.validate_dims("parameter initialization", "Lcorr", "matrix_d", context__.to_vec((n_varying_covars * correlated_rw),(n_varying_covars * correlated_rw))); + Eigen::Matrix Lcorr((n_varying_covars * correlated_rw), (n_varying_covars * correlated_rw)); + size_t Lcorr_j_2_max__ = (n_varying_covars * correlated_rw); + size_t Lcorr_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < Lcorr_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < Lcorr_j_1_max__; ++j_1__) { + Lcorr(j_1__, j_2__) = vals_r__[pos__++]; + } + } + try { + writer__.cholesky_factor_corr_unconstrain(Lcorr); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable Lcorr: ") + e.what()), current_statement_begin__, prog_reader__()); + } + current_statement_begin__ = 33; + if (!(context__.contains_r("sigma"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable sigma missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("sigma"); + pos__ = 0U; + validate_non_negative_index("sigma", "n_varying_covars", n_varying_covars); + context__.validate_dims("parameter initialization", "sigma", "vector_d", context__.to_vec(n_varying_covars)); + Eigen::Matrix sigma(n_varying_covars); + size_t sigma_j_1_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < sigma_j_1_max__; ++j_1__) { + sigma(j_1__) = vals_r__[pos__++]; + } + try { + writer__.vector_lb_unconstrain(0, sigma); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable sigma: ") + e.what()), current_statement_begin__, prog_reader__()); + } + current_statement_begin__ = 34; + if (!(context__.contains_r("phi"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable phi missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("phi"); + pos__ = 0U; + validate_non_negative_index("phi", "1", 1); + context__.validate_dims("parameter initialization", "phi", "vector_d", context__.to_vec(1)); + Eigen::Matrix phi(1); + size_t phi_j_1_max__ = 1; + for (size_t j_1__ = 0; j_1__ < phi_j_1_max__; ++j_1__) { + phi(j_1__) = vals_r__[pos__++]; + } + try { + writer__.vector_lb_unconstrain(0, phi); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable phi: ") + e.what()), current_statement_begin__, prog_reader__()); + } + current_statement_begin__ = 35; + if (!(context__.contains_r("nu"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable nu missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("nu"); + pos__ = 0U; + validate_non_negative_index("nu", "est_df", est_df); + context__.validate_dims("parameter initialization", "nu", "vector_d", context__.to_vec(est_df)); + Eigen::Matrix nu(est_df); + size_t nu_j_1_max__ = est_df; + for (size_t j_1__ = 0; j_1__ < nu_j_1_max__; ++j_1__) { + nu(j_1__) = vals_r__[pos__++]; + } + try { + writer__.vector_lb_unconstrain(0, nu); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable nu: ") + e.what()), current_statement_begin__, prog_reader__()); + } + current_statement_begin__ = 36; + if (!(context__.contains_r("missing_fixed"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable missing_fixed missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("missing_fixed"); + pos__ = 0U; + validate_non_negative_index("missing_fixed", "n_fixed_NAs", n_fixed_NAs); + context__.validate_dims("parameter initialization", "missing_fixed", "vector_d", context__.to_vec(n_fixed_NAs)); + Eigen::Matrix missing_fixed(n_fixed_NAs); + size_t missing_fixed_j_1_max__ = n_fixed_NAs; + for (size_t j_1__ = 0; j_1__ < missing_fixed_j_1_max__; ++j_1__) { + missing_fixed(j_1__) = vals_r__[pos__++]; + } + try { + writer__.vector_unconstrain(missing_fixed); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable missing_fixed: ") + e.what()), current_statement_begin__, prog_reader__()); + } + current_statement_begin__ = 37; + if (!(context__.contains_r("missing_varying"))) + stan::lang::rethrow_located(std::runtime_error(std::string("Variable missing_varying missing")), current_statement_begin__, prog_reader__()); + vals_r__ = context__.vals_r("missing_varying"); + pos__ = 0U; + validate_non_negative_index("missing_varying", "n_varying_NAs", n_varying_NAs); + context__.validate_dims("parameter initialization", "missing_varying", "vector_d", context__.to_vec(n_varying_NAs)); + Eigen::Matrix missing_varying(n_varying_NAs); + size_t missing_varying_j_1_max__ = n_varying_NAs; + for (size_t j_1__ = 0; j_1__ < missing_varying_j_1_max__; ++j_1__) { + missing_varying(j_1__) = vals_r__[pos__++]; + } + try { + writer__.vector_unconstrain(missing_varying); + } catch (const std::exception& e) { + stan::lang::rethrow_located(std::runtime_error(std::string("Error transforming variable missing_varying: ") + e.what()), current_statement_begin__, prog_reader__()); + } + params_r__ = writer__.data_r(); + params_i__ = writer__.data_i(); + } + void transform_inits(const stan::io::var_context& context, + Eigen::Matrix& params_r, + std::ostream* pstream__) const { + std::vector params_r_vec; + std::vector params_i_vec; + transform_inits(context, params_i_vec, params_r_vec, pstream__); + params_r.resize(params_r_vec.size()); + for (int i = 0; i < params_r.size(); ++i) + params_r(i) = params_r_vec[i]; + } + template + T__ log_prob(std::vector& params_r__, + std::vector& params_i__, + std::ostream* pstream__ = 0) const { + typedef T__ local_scalar_t__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + (void) DUMMY_VAR__; // dummy to suppress unused var warning + T__ lp__(0.0); + stan::math::accumulator lp_accum__; + try { + stan::io::reader in__(params_r__, params_i__); + // model parameters + current_statement_begin__ = 29; + Eigen::Matrix b_fixed; + (void) b_fixed; // dummy to suppress unused var warning + if (jacobian__) + b_fixed = in__.vector_constrain(n_fixed_covars, lp__); + else + b_fixed = in__.vector_constrain(n_fixed_covars); + current_statement_begin__ = 30; + Eigen::Matrix b_devs0; + (void) b_devs0; // dummy to suppress unused var warning + if (jacobian__) + b_devs0 = in__.vector_constrain(n_varying_covars, lp__); + else + b_devs0 = in__.vector_constrain(n_varying_covars); + current_statement_begin__ = 31; + std::vector > b_devs; + size_t b_devs_d_0_max__ = (nT - 1); + b_devs.reserve(b_devs_d_0_max__); + for (size_t d_0__ = 0; d_0__ < b_devs_d_0_max__; ++d_0__) { + if (jacobian__) + b_devs.push_back(in__.vector_constrain(n_varying_covars, lp__)); + else + b_devs.push_back(in__.vector_constrain(n_varying_covars)); + } + current_statement_begin__ = 32; + Eigen::Matrix Lcorr; + (void) Lcorr; // dummy to suppress unused var warning + if (jacobian__) + Lcorr = in__.cholesky_factor_corr_constrain((n_varying_covars * correlated_rw), lp__); + else + Lcorr = in__.cholesky_factor_corr_constrain((n_varying_covars * correlated_rw)); + current_statement_begin__ = 33; + Eigen::Matrix sigma; + (void) sigma; // dummy to suppress unused var warning + if (jacobian__) + sigma = in__.vector_lb_constrain(0, n_varying_covars, lp__); + else + sigma = in__.vector_lb_constrain(0, n_varying_covars); + current_statement_begin__ = 34; + Eigen::Matrix phi; + (void) phi; // dummy to suppress unused var warning + if (jacobian__) + phi = in__.vector_lb_constrain(0, 1, lp__); + else + phi = in__.vector_lb_constrain(0, 1); + current_statement_begin__ = 35; + Eigen::Matrix nu; + (void) nu; // dummy to suppress unused var warning + if (jacobian__) + nu = in__.vector_lb_constrain(0, est_df, lp__); + else + nu = in__.vector_lb_constrain(0, est_df); + current_statement_begin__ = 36; + Eigen::Matrix missing_fixed; + (void) missing_fixed; // dummy to suppress unused var warning + if (jacobian__) + missing_fixed = in__.vector_constrain(n_fixed_NAs, lp__); + else + missing_fixed = in__.vector_constrain(n_fixed_NAs); + current_statement_begin__ = 37; + Eigen::Matrix missing_varying; + (void) missing_varying; // dummy to suppress unused var warning + if (jacobian__) + missing_varying = in__.vector_constrain(n_varying_NAs, lp__); + else + missing_varying = in__.vector_constrain(n_varying_NAs); + // transformed parameters + current_statement_begin__ = 40; + validate_non_negative_index("b_varying", "n_varying_covars", n_varying_covars); + validate_non_negative_index("b_varying", "nT", nT); + std::vector > b_varying(nT, Eigen::Matrix(n_varying_covars)); + stan::math::initialize(b_varying, DUMMY_VAR__); + stan::math::fill(b_varying, DUMMY_VAR__); + current_statement_begin__ = 43; + validate_non_negative_index("R", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + validate_non_negative_index("R", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + Eigen::Matrix R((n_varying_covars * correlated_rw), (n_varying_covars * correlated_rw)); + stan::math::initialize(R, DUMMY_VAR__); + stan::math::fill(R, DUMMY_VAR__); + current_statement_begin__ = 44; + validate_non_negative_index("Sigma", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + validate_non_negative_index("Sigma", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + Eigen::Matrix Sigma((n_varying_covars * correlated_rw), (n_varying_covars * correlated_rw)); + stan::math::initialize(Sigma, DUMMY_VAR__); + stan::math::fill(Sigma, DUMMY_VAR__); + current_statement_begin__ = 45; + validate_non_negative_index("eta", "nT", nT); + Eigen::Matrix eta(nT); + stan::math::initialize(eta, DUMMY_VAR__); + stan::math::fill(eta, DUMMY_VAR__); + current_statement_begin__ = 46; + validate_non_negative_index("X_fixed", "nT", nT); + validate_non_negative_index("X_fixed", "n_fixed_covars", n_fixed_covars); + Eigen::Matrix X_fixed(nT, n_fixed_covars); + stan::math::initialize(X_fixed, DUMMY_VAR__); + stan::math::fill(X_fixed, DUMMY_VAR__); + current_statement_begin__ = 47; + validate_non_negative_index("X_varying", "nT", nT); + validate_non_negative_index("X_varying", "n_varying_covars", n_varying_covars); + Eigen::Matrix X_varying(nT, n_varying_covars); + stan::math::initialize(X_varying, DUMMY_VAR__); + stan::math::fill(X_varying, DUMMY_VAR__); + // transformed parameters block statements + current_statement_begin__ = 50; + if (as_bool(logical_eq(correlated_rw, 1))) { + current_statement_begin__ = 51; + stan::math::assign(R, multiply_lower_tri_self_transpose(Lcorr)); + current_statement_begin__ = 52; + stan::math::assign(Sigma, quad_form_diag(R, sigma)); + } + current_statement_begin__ = 56; + if (as_bool(logical_gt(n_fixed_covars, 0))) { + current_statement_begin__ = 57; + for (int i = 1; i <= fixed_N; ++i) { + current_statement_begin__ = 58; + stan::model::assign(X_fixed, + stan::model::cons_list(stan::model::index_uni(get_base1(fixed_time_indx, i, "fixed_time_indx", 1)), stan::model::cons_list(stan::model::index_uni(get_base1(fixed_var_indx, i, "fixed_var_indx", 1)), stan::model::nil_index_list())), + get_base1(fixed_x_value, i, "fixed_x_value", 1), + "assigning variable X_fixed"); + } + current_statement_begin__ = 61; + for (int i = 1; i <= n_fixed_NAs; ++i) { + current_statement_begin__ = 62; + stan::model::assign(X_fixed, + stan::model::cons_list(stan::model::index_uni(get_base1(fixed_time_indx, get_base1(fixed_NAs, i, "fixed_NAs", 1), "fixed_time_indx", 1)), stan::model::cons_list(stan::model::index_uni(get_base1(fixed_var_indx, get_base1(fixed_NAs, i, "fixed_NAs", 1), "fixed_var_indx", 1)), stan::model::nil_index_list())), + get_base1(missing_fixed, i, "missing_fixed", 1), + "assigning variable X_fixed"); + } + } + current_statement_begin__ = 65; + if (as_bool(logical_gt(n_varying_covars, 0))) { + current_statement_begin__ = 66; + for (int i = 1; i <= varying_N; ++i) { + current_statement_begin__ = 67; + stan::model::assign(X_varying, + stan::model::cons_list(stan::model::index_uni(get_base1(varying_time_indx, i, "varying_time_indx", 1)), stan::model::cons_list(stan::model::index_uni(get_base1(varying_var_indx, i, "varying_var_indx", 1)), stan::model::nil_index_list())), + get_base1(varying_x_value, i, "varying_x_value", 1), + "assigning variable X_varying"); + } + current_statement_begin__ = 70; + for (int i = 1; i <= n_varying_NAs; ++i) { + current_statement_begin__ = 71; + stan::model::assign(X_varying, + stan::model::cons_list(stan::model::index_uni(get_base1(varying_time_indx, get_base1(varying_NAs, i, "varying_NAs", 1), "varying_time_indx", 1)), stan::model::cons_list(stan::model::index_uni(get_base1(varying_var_indx, get_base1(varying_NAs, i, "varying_NAs", 1), "varying_var_indx", 1)), stan::model::nil_index_list())), + get_base1(missing_varying, i, "missing_varying", 1), + "assigning variable X_varying"); + } + } + current_statement_begin__ = 76; + stan::model::assign(b_varying, + stan::model::cons_list(stan::model::index_uni(1), stan::model::nil_index_list()), + b_devs0, + "assigning variable b_varying"); + current_statement_begin__ = 77; + for (int t = 2; t <= nT; ++t) { + current_statement_begin__ = 78; + stan::model::assign(b_varying, + stan::model::cons_list(stan::model::index_uni(t), stan::model::nil_index_list()), + add(get_base1(b_varying, (t - 1), "b_varying", 1), get_base1(b_devs, (t - 1), "b_devs", 1)), + "assigning variable b_varying"); + } + current_statement_begin__ = 82; + for (int t = 1; t <= nT; ++t) { + current_statement_begin__ = 82; + stan::model::assign(eta, + stan::model::cons_list(stan::model::index_uni(t), stan::model::nil_index_list()), + 0, + "assigning variable eta"); + } + current_statement_begin__ = 83; + if (as_bool(logical_gt(n_fixed_covars, 0))) { + current_statement_begin__ = 83; + stan::math::assign(eta, add(eta, multiply(X_fixed, b_fixed))); + } + current_statement_begin__ = 84; + if (as_bool(logical_gt(n_varying_covars, 0))) { + current_statement_begin__ = 85; + for (int t = 1; t <= nT; ++t) { + current_statement_begin__ = 86; + stan::model::assign(eta, + stan::model::cons_list(stan::model::index_uni(t), stan::model::nil_index_list()), + (get_base1(eta, t, "eta", 1) + multiply(get_base1(X_varying, t, "X_varying", 1), get_base1(b_varying, t, "b_varying", 1))), + "assigning variable eta"); + } + } + // validate transformed parameters + const char* function__ = "validate transformed params"; + (void) function__; // dummy to suppress unused var warning + current_statement_begin__ = 40; + size_t b_varying_k_0_max__ = nT; + size_t b_varying_j_1_max__ = n_varying_covars; + for (size_t k_0__ = 0; k_0__ < b_varying_k_0_max__; ++k_0__) { + for (size_t j_1__ = 0; j_1__ < b_varying_j_1_max__; ++j_1__) { + if (stan::math::is_uninitialized(b_varying[k_0__](j_1__))) { + std::stringstream msg__; + msg__ << "Undefined transformed parameter: b_varying" << "[" << k_0__ << "]" << "(" << j_1__ << ")"; + stan::lang::rethrow_located(std::runtime_error(std::string("Error initializing variable b_varying: ") + msg__.str()), current_statement_begin__, prog_reader__()); + } + } + } + current_statement_begin__ = 43; + size_t R_j_1_max__ = (n_varying_covars * correlated_rw); + size_t R_j_2_max__ = (n_varying_covars * correlated_rw); + for (size_t j_1__ = 0; j_1__ < R_j_1_max__; ++j_1__) { + for (size_t j_2__ = 0; j_2__ < R_j_2_max__; ++j_2__) { + if (stan::math::is_uninitialized(R(j_1__, j_2__))) { + std::stringstream msg__; + msg__ << "Undefined transformed parameter: R" << "(" << j_1__ << ", " << j_2__ << ")"; + stan::lang::rethrow_located(std::runtime_error(std::string("Error initializing variable R: ") + msg__.str()), current_statement_begin__, prog_reader__()); + } + } + } + current_statement_begin__ = 44; + size_t Sigma_j_1_max__ = (n_varying_covars * correlated_rw); + size_t Sigma_j_2_max__ = (n_varying_covars * correlated_rw); + for (size_t j_1__ = 0; j_1__ < Sigma_j_1_max__; ++j_1__) { + for (size_t j_2__ = 0; j_2__ < Sigma_j_2_max__; ++j_2__) { + if (stan::math::is_uninitialized(Sigma(j_1__, j_2__))) { + std::stringstream msg__; + msg__ << "Undefined transformed parameter: Sigma" << "(" << j_1__ << ", " << j_2__ << ")"; + stan::lang::rethrow_located(std::runtime_error(std::string("Error initializing variable Sigma: ") + msg__.str()), current_statement_begin__, prog_reader__()); + } + } + } + current_statement_begin__ = 45; + size_t eta_j_1_max__ = nT; + for (size_t j_1__ = 0; j_1__ < eta_j_1_max__; ++j_1__) { + if (stan::math::is_uninitialized(eta(j_1__))) { + std::stringstream msg__; + msg__ << "Undefined transformed parameter: eta" << "(" << j_1__ << ")"; + stan::lang::rethrow_located(std::runtime_error(std::string("Error initializing variable eta: ") + msg__.str()), current_statement_begin__, prog_reader__()); + } + } + current_statement_begin__ = 46; + size_t X_fixed_j_1_max__ = nT; + size_t X_fixed_j_2_max__ = n_fixed_covars; + for (size_t j_1__ = 0; j_1__ < X_fixed_j_1_max__; ++j_1__) { + for (size_t j_2__ = 0; j_2__ < X_fixed_j_2_max__; ++j_2__) { + if (stan::math::is_uninitialized(X_fixed(j_1__, j_2__))) { + std::stringstream msg__; + msg__ << "Undefined transformed parameter: X_fixed" << "(" << j_1__ << ", " << j_2__ << ")"; + stan::lang::rethrow_located(std::runtime_error(std::string("Error initializing variable X_fixed: ") + msg__.str()), current_statement_begin__, prog_reader__()); + } + } + } + current_statement_begin__ = 47; + size_t X_varying_j_1_max__ = nT; + size_t X_varying_j_2_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < X_varying_j_1_max__; ++j_1__) { + for (size_t j_2__ = 0; j_2__ < X_varying_j_2_max__; ++j_2__) { + if (stan::math::is_uninitialized(X_varying(j_1__, j_2__))) { + std::stringstream msg__; + msg__ << "Undefined transformed parameter: X_varying" << "(" << j_1__ << ", " << j_2__ << ")"; + stan::lang::rethrow_located(std::runtime_error(std::string("Error initializing variable X_varying: ") + msg__.str()), current_statement_begin__, prog_reader__()); + } + } + } + // model body + current_statement_begin__ = 91; + lp_accum__.add(cauchy_log(sigma, 0, 5)); + current_statement_begin__ = 92; + lp_accum__.add(lkj_corr_cholesky_log(Lcorr, 2.0)); + current_statement_begin__ = 93; + lp_accum__.add(student_t_log(phi, 3, 0, 2)); + current_statement_begin__ = 94; + lp_accum__.add(normal_log(b_fixed, 0, 1)); + current_statement_begin__ = 95; + lp_accum__.add(student_t_log(nu, 3, 0, 2)); + current_statement_begin__ = 97; + lp_accum__.add(normal_log(missing_fixed, 0, 1)); + current_statement_begin__ = 98; + lp_accum__.add(normal_log(missing_varying, 0, 1)); + current_statement_begin__ = 99; + lp_accum__.add(normal_log(b_devs0, 0, 1)); + current_statement_begin__ = 100; + if (as_bool(logical_eq(est_df, 0))) { + current_statement_begin__ = 101; + if (as_bool(logical_eq(correlated_rw, 1))) { + current_statement_begin__ = 102; + for (int t = 1; t <= (nT - 1); ++t) { + current_statement_begin__ = 103; + lp_accum__.add(multi_normal_log(get_base1(b_devs, t, "b_devs", 1), zeros, Sigma)); + } + } else { + current_statement_begin__ = 106; + for (int t = 1; t <= (nT - 1); ++t) { + current_statement_begin__ = 107; + lp_accum__.add(normal_log(get_base1(b_devs, t, "b_devs", 1), zeros, sigma)); + } + } + } else { + current_statement_begin__ = 111; + if (as_bool(logical_eq(correlated_rw, 1))) { + current_statement_begin__ = 112; + for (int t = 1; t <= (nT - 1); ++t) { + current_statement_begin__ = 113; + lp_accum__.add(multi_student_t_log(get_base1(b_devs, t, "b_devs", 1), get_base1(nu, 1, "nu", 1), zeros, Sigma)); + } + } else { + current_statement_begin__ = 116; + for (int t = 1; t <= (nT - 1); ++t) { + current_statement_begin__ = 117; + lp_accum__.add(student_t_log(get_base1(b_devs, t, "b_devs", 1), get_base1(nu, 1, "nu", 1), zeros, sigma)); + } + } + } + current_statement_begin__ = 122; + if (as_bool(logical_eq(family, 1))) { + current_statement_begin__ = 123; + lp_accum__.add(normal_log(y, eta, get_base1(phi, 1, "phi", 1))); + } + current_statement_begin__ = 125; + if (as_bool(logical_eq(family, 2))) { + current_statement_begin__ = 126; + lp_accum__.add(bernoulli_logit_log(y_int, eta)); + } + current_statement_begin__ = 128; + if (as_bool(logical_eq(family, 3))) { + current_statement_begin__ = 129; + lp_accum__.add(poisson_log_log(y_int, eta)); + } + current_statement_begin__ = 131; + if (as_bool(logical_eq(family, 4))) { + current_statement_begin__ = 132; + lp_accum__.add(neg_binomial_2_log_log(y_int, eta, get_base1(phi, 1, "phi", 1))); + } + current_statement_begin__ = 134; + if (as_bool(logical_eq(family, 5))) { + current_statement_begin__ = 135; + lp_accum__.add(gamma_log(y, get_base1(phi, 1, "phi", 1), elt_divide(get_base1(phi, 1, "phi", 1), stan::math::exp(eta)))); + } + current_statement_begin__ = 137; + if (as_bool(logical_eq(family, 6))) { + current_statement_begin__ = 138; + lp_accum__.add(lognormal_log(y, eta, get_base1(phi, 1, "phi", 1))); + } + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); + // Next line prevents compiler griping about no return + throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); + } + lp_accum__.add(lp__); + return lp_accum__.sum(); + } // log_prob() + template + T_ log_prob(Eigen::Matrix& params_r, + std::ostream* pstream = 0) const { + std::vector vec_params_r; + vec_params_r.reserve(params_r.size()); + for (int i = 0; i < params_r.size(); ++i) + vec_params_r.push_back(params_r(i)); + std::vector vec_params_i; + return log_prob(vec_params_r, vec_params_i, pstream); + } + void get_param_names(std::vector& names__) const { + names__.resize(0); + names__.push_back("b_fixed"); + names__.push_back("b_devs0"); + names__.push_back("b_devs"); + names__.push_back("Lcorr"); + names__.push_back("sigma"); + names__.push_back("phi"); + names__.push_back("nu"); + names__.push_back("missing_fixed"); + names__.push_back("missing_varying"); + names__.push_back("b_varying"); + names__.push_back("R"); + names__.push_back("Sigma"); + names__.push_back("eta"); + names__.push_back("X_fixed"); + names__.push_back("X_varying"); + names__.push_back("log_lik"); + } + void get_dims(std::vector >& dimss__) const { + dimss__.resize(0); + std::vector dims__; + dims__.resize(0); + dims__.push_back(n_fixed_covars); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(n_varying_covars); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back((nT - 1)); + dims__.push_back(n_varying_covars); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back((n_varying_covars * correlated_rw)); + dims__.push_back((n_varying_covars * correlated_rw)); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(n_varying_covars); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(1); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(est_df); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(n_fixed_NAs); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(n_varying_NAs); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(nT); + dims__.push_back(n_varying_covars); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back((n_varying_covars * correlated_rw)); + dims__.push_back((n_varying_covars * correlated_rw)); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back((n_varying_covars * correlated_rw)); + dims__.push_back((n_varying_covars * correlated_rw)); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(nT); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(nT); + dims__.push_back(n_fixed_covars); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(nT); + dims__.push_back(n_varying_covars); + dimss__.push_back(dims__); + dims__.resize(0); + dims__.push_back(N); + dimss__.push_back(dims__); + } + template + void write_array(RNG& base_rng__, + std::vector& params_r__, + std::vector& params_i__, + std::vector& vars__, + bool include_tparams__ = true, + bool include_gqs__ = true, + std::ostream* pstream__ = 0) const { + typedef double local_scalar_t__; + vars__.resize(0); + stan::io::reader in__(params_r__, params_i__); + static const char* function__ = "model_dlm_namespace::write_array"; + (void) function__; // dummy to suppress unused var warning + // read-transform, write parameters + Eigen::Matrix b_fixed = in__.vector_constrain(n_fixed_covars); + size_t b_fixed_j_1_max__ = n_fixed_covars; + for (size_t j_1__ = 0; j_1__ < b_fixed_j_1_max__; ++j_1__) { + vars__.push_back(b_fixed(j_1__)); + } + Eigen::Matrix b_devs0 = in__.vector_constrain(n_varying_covars); + size_t b_devs0_j_1_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < b_devs0_j_1_max__; ++j_1__) { + vars__.push_back(b_devs0(j_1__)); + } + std::vector > b_devs; + size_t b_devs_d_0_max__ = (nT - 1); + b_devs.reserve(b_devs_d_0_max__); + for (size_t d_0__ = 0; d_0__ < b_devs_d_0_max__; ++d_0__) { + b_devs.push_back(in__.vector_constrain(n_varying_covars)); + } + size_t b_devs_j_1_max__ = n_varying_covars; + size_t b_devs_k_0_max__ = (nT - 1); + for (size_t j_1__ = 0; j_1__ < b_devs_j_1_max__; ++j_1__) { + for (size_t k_0__ = 0; k_0__ < b_devs_k_0_max__; ++k_0__) { + vars__.push_back(b_devs[k_0__](j_1__)); + } + } + Eigen::Matrix Lcorr = in__.cholesky_factor_corr_constrain((n_varying_covars * correlated_rw)); + size_t Lcorr_j_2_max__ = (n_varying_covars * correlated_rw); + size_t Lcorr_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < Lcorr_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < Lcorr_j_1_max__; ++j_1__) { + vars__.push_back(Lcorr(j_1__, j_2__)); + } + } + Eigen::Matrix sigma = in__.vector_lb_constrain(0, n_varying_covars); + size_t sigma_j_1_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < sigma_j_1_max__; ++j_1__) { + vars__.push_back(sigma(j_1__)); + } + Eigen::Matrix phi = in__.vector_lb_constrain(0, 1); + size_t phi_j_1_max__ = 1; + for (size_t j_1__ = 0; j_1__ < phi_j_1_max__; ++j_1__) { + vars__.push_back(phi(j_1__)); + } + Eigen::Matrix nu = in__.vector_lb_constrain(0, est_df); + size_t nu_j_1_max__ = est_df; + for (size_t j_1__ = 0; j_1__ < nu_j_1_max__; ++j_1__) { + vars__.push_back(nu(j_1__)); + } + Eigen::Matrix missing_fixed = in__.vector_constrain(n_fixed_NAs); + size_t missing_fixed_j_1_max__ = n_fixed_NAs; + for (size_t j_1__ = 0; j_1__ < missing_fixed_j_1_max__; ++j_1__) { + vars__.push_back(missing_fixed(j_1__)); + } + Eigen::Matrix missing_varying = in__.vector_constrain(n_varying_NAs); + size_t missing_varying_j_1_max__ = n_varying_NAs; + for (size_t j_1__ = 0; j_1__ < missing_varying_j_1_max__; ++j_1__) { + vars__.push_back(missing_varying(j_1__)); + } + double lp__ = 0.0; + (void) lp__; // dummy to suppress unused var warning + stan::math::accumulator lp_accum__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + (void) DUMMY_VAR__; // suppress unused var warning + if (!include_tparams__ && !include_gqs__) return; + try { + // declare and define transformed parameters + current_statement_begin__ = 40; + validate_non_negative_index("b_varying", "n_varying_covars", n_varying_covars); + validate_non_negative_index("b_varying", "nT", nT); + std::vector > b_varying(nT, Eigen::Matrix(n_varying_covars)); + stan::math::initialize(b_varying, DUMMY_VAR__); + stan::math::fill(b_varying, DUMMY_VAR__); + current_statement_begin__ = 43; + validate_non_negative_index("R", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + validate_non_negative_index("R", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + Eigen::Matrix R((n_varying_covars * correlated_rw), (n_varying_covars * correlated_rw)); + stan::math::initialize(R, DUMMY_VAR__); + stan::math::fill(R, DUMMY_VAR__); + current_statement_begin__ = 44; + validate_non_negative_index("Sigma", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + validate_non_negative_index("Sigma", "(n_varying_covars * correlated_rw)", (n_varying_covars * correlated_rw)); + Eigen::Matrix Sigma((n_varying_covars * correlated_rw), (n_varying_covars * correlated_rw)); + stan::math::initialize(Sigma, DUMMY_VAR__); + stan::math::fill(Sigma, DUMMY_VAR__); + current_statement_begin__ = 45; + validate_non_negative_index("eta", "nT", nT); + Eigen::Matrix eta(nT); + stan::math::initialize(eta, DUMMY_VAR__); + stan::math::fill(eta, DUMMY_VAR__); + current_statement_begin__ = 46; + validate_non_negative_index("X_fixed", "nT", nT); + validate_non_negative_index("X_fixed", "n_fixed_covars", n_fixed_covars); + Eigen::Matrix X_fixed(nT, n_fixed_covars); + stan::math::initialize(X_fixed, DUMMY_VAR__); + stan::math::fill(X_fixed, DUMMY_VAR__); + current_statement_begin__ = 47; + validate_non_negative_index("X_varying", "nT", nT); + validate_non_negative_index("X_varying", "n_varying_covars", n_varying_covars); + Eigen::Matrix X_varying(nT, n_varying_covars); + stan::math::initialize(X_varying, DUMMY_VAR__); + stan::math::fill(X_varying, DUMMY_VAR__); + // do transformed parameters statements + current_statement_begin__ = 50; + if (as_bool(logical_eq(correlated_rw, 1))) { + current_statement_begin__ = 51; + stan::math::assign(R, multiply_lower_tri_self_transpose(Lcorr)); + current_statement_begin__ = 52; + stan::math::assign(Sigma, quad_form_diag(R, sigma)); + } + current_statement_begin__ = 56; + if (as_bool(logical_gt(n_fixed_covars, 0))) { + current_statement_begin__ = 57; + for (int i = 1; i <= fixed_N; ++i) { + current_statement_begin__ = 58; + stan::model::assign(X_fixed, + stan::model::cons_list(stan::model::index_uni(get_base1(fixed_time_indx, i, "fixed_time_indx", 1)), stan::model::cons_list(stan::model::index_uni(get_base1(fixed_var_indx, i, "fixed_var_indx", 1)), stan::model::nil_index_list())), + get_base1(fixed_x_value, i, "fixed_x_value", 1), + "assigning variable X_fixed"); + } + current_statement_begin__ = 61; + for (int i = 1; i <= n_fixed_NAs; ++i) { + current_statement_begin__ = 62; + stan::model::assign(X_fixed, + stan::model::cons_list(stan::model::index_uni(get_base1(fixed_time_indx, get_base1(fixed_NAs, i, "fixed_NAs", 1), "fixed_time_indx", 1)), stan::model::cons_list(stan::model::index_uni(get_base1(fixed_var_indx, get_base1(fixed_NAs, i, "fixed_NAs", 1), "fixed_var_indx", 1)), stan::model::nil_index_list())), + get_base1(missing_fixed, i, "missing_fixed", 1), + "assigning variable X_fixed"); + } + } + current_statement_begin__ = 65; + if (as_bool(logical_gt(n_varying_covars, 0))) { + current_statement_begin__ = 66; + for (int i = 1; i <= varying_N; ++i) { + current_statement_begin__ = 67; + stan::model::assign(X_varying, + stan::model::cons_list(stan::model::index_uni(get_base1(varying_time_indx, i, "varying_time_indx", 1)), stan::model::cons_list(stan::model::index_uni(get_base1(varying_var_indx, i, "varying_var_indx", 1)), stan::model::nil_index_list())), + get_base1(varying_x_value, i, "varying_x_value", 1), + "assigning variable X_varying"); + } + current_statement_begin__ = 70; + for (int i = 1; i <= n_varying_NAs; ++i) { + current_statement_begin__ = 71; + stan::model::assign(X_varying, + stan::model::cons_list(stan::model::index_uni(get_base1(varying_time_indx, get_base1(varying_NAs, i, "varying_NAs", 1), "varying_time_indx", 1)), stan::model::cons_list(stan::model::index_uni(get_base1(varying_var_indx, get_base1(varying_NAs, i, "varying_NAs", 1), "varying_var_indx", 1)), stan::model::nil_index_list())), + get_base1(missing_varying, i, "missing_varying", 1), + "assigning variable X_varying"); + } + } + current_statement_begin__ = 76; + stan::model::assign(b_varying, + stan::model::cons_list(stan::model::index_uni(1), stan::model::nil_index_list()), + b_devs0, + "assigning variable b_varying"); + current_statement_begin__ = 77; + for (int t = 2; t <= nT; ++t) { + current_statement_begin__ = 78; + stan::model::assign(b_varying, + stan::model::cons_list(stan::model::index_uni(t), stan::model::nil_index_list()), + add(get_base1(b_varying, (t - 1), "b_varying", 1), get_base1(b_devs, (t - 1), "b_devs", 1)), + "assigning variable b_varying"); + } + current_statement_begin__ = 82; + for (int t = 1; t <= nT; ++t) { + current_statement_begin__ = 82; + stan::model::assign(eta, + stan::model::cons_list(stan::model::index_uni(t), stan::model::nil_index_list()), + 0, + "assigning variable eta"); + } + current_statement_begin__ = 83; + if (as_bool(logical_gt(n_fixed_covars, 0))) { + current_statement_begin__ = 83; + stan::math::assign(eta, add(eta, multiply(X_fixed, b_fixed))); + } + current_statement_begin__ = 84; + if (as_bool(logical_gt(n_varying_covars, 0))) { + current_statement_begin__ = 85; + for (int t = 1; t <= nT; ++t) { + current_statement_begin__ = 86; + stan::model::assign(eta, + stan::model::cons_list(stan::model::index_uni(t), stan::model::nil_index_list()), + (get_base1(eta, t, "eta", 1) + multiply(get_base1(X_varying, t, "X_varying", 1), get_base1(b_varying, t, "b_varying", 1))), + "assigning variable eta"); + } + } + if (!include_gqs__ && !include_tparams__) return; + // validate transformed parameters + const char* function__ = "validate transformed params"; + (void) function__; // dummy to suppress unused var warning + // write transformed parameters + if (include_tparams__) { + size_t b_varying_j_1_max__ = n_varying_covars; + size_t b_varying_k_0_max__ = nT; + for (size_t j_1__ = 0; j_1__ < b_varying_j_1_max__; ++j_1__) { + for (size_t k_0__ = 0; k_0__ < b_varying_k_0_max__; ++k_0__) { + vars__.push_back(b_varying[k_0__](j_1__)); + } + } + size_t R_j_2_max__ = (n_varying_covars * correlated_rw); + size_t R_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < R_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < R_j_1_max__; ++j_1__) { + vars__.push_back(R(j_1__, j_2__)); + } + } + size_t Sigma_j_2_max__ = (n_varying_covars * correlated_rw); + size_t Sigma_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < Sigma_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < Sigma_j_1_max__; ++j_1__) { + vars__.push_back(Sigma(j_1__, j_2__)); + } + } + size_t eta_j_1_max__ = nT; + for (size_t j_1__ = 0; j_1__ < eta_j_1_max__; ++j_1__) { + vars__.push_back(eta(j_1__)); + } + size_t X_fixed_j_2_max__ = n_fixed_covars; + size_t X_fixed_j_1_max__ = nT; + for (size_t j_2__ = 0; j_2__ < X_fixed_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < X_fixed_j_1_max__; ++j_1__) { + vars__.push_back(X_fixed(j_1__, j_2__)); + } + } + size_t X_varying_j_2_max__ = n_varying_covars; + size_t X_varying_j_1_max__ = nT; + for (size_t j_2__ = 0; j_2__ < X_varying_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < X_varying_j_1_max__; ++j_1__) { + vars__.push_back(X_varying(j_1__, j_2__)); + } + } + } + if (!include_gqs__) return; + // declare and define generated quantities + current_statement_begin__ = 142; + validate_non_negative_index("log_lik", "N", N); + Eigen::Matrix log_lik(N); + stan::math::initialize(log_lik, DUMMY_VAR__); + stan::math::fill(log_lik, DUMMY_VAR__); + // generated quantities statements + current_statement_begin__ = 143; + if (as_bool(logical_eq(family, 1))) { + current_statement_begin__ = 144; + for (int n = 1; n <= N; ++n) { + current_statement_begin__ = 144; + stan::model::assign(log_lik, + stan::model::cons_list(stan::model::index_uni(n), stan::model::nil_index_list()), + normal_log(get_base1(y, n, "y", 1), get_base1(eta, n, "eta", 1), get_base1(phi, 1, "phi", 1)), + "assigning variable log_lik"); + } + } + current_statement_begin__ = 146; + if (as_bool(logical_eq(family, 2))) { + current_statement_begin__ = 147; + for (int n = 1; n <= N; ++n) { + current_statement_begin__ = 147; + stan::model::assign(log_lik, + stan::model::cons_list(stan::model::index_uni(n), stan::model::nil_index_list()), + bernoulli_log(get_base1(y_int, n, "y_int", 1), inv_logit(get_base1(eta, n, "eta", 1))), + "assigning variable log_lik"); + } + } + current_statement_begin__ = 149; + if (as_bool(logical_eq(family, 3))) { + current_statement_begin__ = 150; + for (int n = 1; n <= N; ++n) { + current_statement_begin__ = 150; + stan::model::assign(log_lik, + stan::model::cons_list(stan::model::index_uni(n), stan::model::nil_index_list()), + poisson_log(get_base1(y_int, n, "y_int", 1), stan::math::exp(get_base1(eta, n, "eta", 1))), + "assigning variable log_lik"); + } + } + current_statement_begin__ = 152; + if (as_bool(logical_eq(family, 4))) { + current_statement_begin__ = 153; + for (int n = 1; n <= N; ++n) { + current_statement_begin__ = 153; + stan::model::assign(log_lik, + stan::model::cons_list(stan::model::index_uni(n), stan::model::nil_index_list()), + normal_log(get_base1(y, n, "y", 1), get_base1(eta, n, "eta", 1), get_base1(phi, 1, "phi", 1)), + "assigning variable log_lik"); + } + } + current_statement_begin__ = 155; + if (as_bool(logical_eq(family, 5))) { + current_statement_begin__ = 156; + for (int n = 1; n <= N; ++n) { + current_statement_begin__ = 156; + stan::model::assign(log_lik, + stan::model::cons_list(stan::model::index_uni(n), stan::model::nil_index_list()), + gamma_log(get_base1(y, n, "y", 1), get_base1(phi, 1, "phi", 1), (get_base1(phi, 1, "phi", 1) / stan::math::exp(get_base1(eta, n, "eta", 1)))), + "assigning variable log_lik"); + } + } + current_statement_begin__ = 158; + if (as_bool(logical_eq(family, 6))) { + current_statement_begin__ = 159; + for (int n = 1; n <= N; ++n) { + current_statement_begin__ = 159; + stan::model::assign(log_lik, + stan::model::cons_list(stan::model::index_uni(n), stan::model::nil_index_list()), + lognormal_log(get_base1(y, n, "y", 1), get_base1(eta, n, "eta", 1), get_base1(phi, 1, "phi", 1)), + "assigning variable log_lik"); + } + } + // validate, write generated quantities + current_statement_begin__ = 142; + size_t log_lik_j_1_max__ = N; + for (size_t j_1__ = 0; j_1__ < log_lik_j_1_max__; ++j_1__) { + vars__.push_back(log_lik(j_1__)); + } + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); + // Next line prevents compiler griping about no return + throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); + } + } + template + void write_array(RNG& base_rng, + Eigen::Matrix& params_r, + Eigen::Matrix& vars, + bool include_tparams = true, + bool include_gqs = true, + std::ostream* pstream = 0) const { + std::vector params_r_vec(params_r.size()); + for (int i = 0; i < params_r.size(); ++i) + params_r_vec[i] = params_r(i); + std::vector vars_vec; + std::vector params_i_vec; + write_array(base_rng, params_r_vec, params_i_vec, vars_vec, include_tparams, include_gqs, pstream); + vars.resize(vars_vec.size()); + for (int i = 0; i < vars.size(); ++i) + vars(i) = vars_vec[i]; + } + std::string model_name() const { + return "model_dlm"; + } + void constrained_param_names(std::vector& param_names__, + bool include_tparams__ = true, + bool include_gqs__ = true) const { + std::stringstream param_name_stream__; + size_t b_fixed_j_1_max__ = n_fixed_covars; + for (size_t j_1__ = 0; j_1__ < b_fixed_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "b_fixed" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t b_devs0_j_1_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < b_devs0_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "b_devs0" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t b_devs_j_1_max__ = n_varying_covars; + size_t b_devs_k_0_max__ = (nT - 1); + for (size_t j_1__ = 0; j_1__ < b_devs_j_1_max__; ++j_1__) { + for (size_t k_0__ = 0; k_0__ < b_devs_k_0_max__; ++k_0__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "b_devs" << '.' << k_0__ + 1 << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t Lcorr_j_2_max__ = (n_varying_covars * correlated_rw); + size_t Lcorr_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < Lcorr_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < Lcorr_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "Lcorr" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t sigma_j_1_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < sigma_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "sigma" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t phi_j_1_max__ = 1; + for (size_t j_1__ = 0; j_1__ < phi_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "phi" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t nu_j_1_max__ = est_df; + for (size_t j_1__ = 0; j_1__ < nu_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "nu" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t missing_fixed_j_1_max__ = n_fixed_NAs; + for (size_t j_1__ = 0; j_1__ < missing_fixed_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "missing_fixed" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t missing_varying_j_1_max__ = n_varying_NAs; + for (size_t j_1__ = 0; j_1__ < missing_varying_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "missing_varying" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + if (!include_gqs__ && !include_tparams__) return; + if (include_tparams__) { + size_t b_varying_j_1_max__ = n_varying_covars; + size_t b_varying_k_0_max__ = nT; + for (size_t j_1__ = 0; j_1__ < b_varying_j_1_max__; ++j_1__) { + for (size_t k_0__ = 0; k_0__ < b_varying_k_0_max__; ++k_0__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "b_varying" << '.' << k_0__ + 1 << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t R_j_2_max__ = (n_varying_covars * correlated_rw); + size_t R_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < R_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < R_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "R" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t Sigma_j_2_max__ = (n_varying_covars * correlated_rw); + size_t Sigma_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < Sigma_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < Sigma_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "Sigma" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t eta_j_1_max__ = nT; + for (size_t j_1__ = 0; j_1__ < eta_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "eta" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t X_fixed_j_2_max__ = n_fixed_covars; + size_t X_fixed_j_1_max__ = nT; + for (size_t j_2__ = 0; j_2__ < X_fixed_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < X_fixed_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "X_fixed" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t X_varying_j_2_max__ = n_varying_covars; + size_t X_varying_j_1_max__ = nT; + for (size_t j_2__ = 0; j_2__ < X_varying_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < X_varying_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "X_varying" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + } + if (!include_gqs__) return; + size_t log_lik_j_1_max__ = N; + for (size_t j_1__ = 0; j_1__ < log_lik_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "log_lik" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + void unconstrained_param_names(std::vector& param_names__, + bool include_tparams__ = true, + bool include_gqs__ = true) const { + std::stringstream param_name_stream__; + size_t b_fixed_j_1_max__ = n_fixed_covars; + for (size_t j_1__ = 0; j_1__ < b_fixed_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "b_fixed" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t b_devs0_j_1_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < b_devs0_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "b_devs0" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t b_devs_j_1_max__ = n_varying_covars; + size_t b_devs_k_0_max__ = (nT - 1); + for (size_t j_1__ = 0; j_1__ < b_devs_j_1_max__; ++j_1__) { + for (size_t k_0__ = 0; k_0__ < b_devs_k_0_max__; ++k_0__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "b_devs" << '.' << k_0__ + 1 << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t Lcorr_j_1_max__ = (((n_varying_covars * correlated_rw) * ((n_varying_covars * correlated_rw) - 1)) / 2); + for (size_t j_1__ = 0; j_1__ < Lcorr_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "Lcorr" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t sigma_j_1_max__ = n_varying_covars; + for (size_t j_1__ = 0; j_1__ < sigma_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "sigma" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t phi_j_1_max__ = 1; + for (size_t j_1__ = 0; j_1__ < phi_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "phi" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t nu_j_1_max__ = est_df; + for (size_t j_1__ = 0; j_1__ < nu_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "nu" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t missing_fixed_j_1_max__ = n_fixed_NAs; + for (size_t j_1__ = 0; j_1__ < missing_fixed_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "missing_fixed" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t missing_varying_j_1_max__ = n_varying_NAs; + for (size_t j_1__ = 0; j_1__ < missing_varying_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "missing_varying" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + if (!include_gqs__ && !include_tparams__) return; + if (include_tparams__) { + size_t b_varying_j_1_max__ = n_varying_covars; + size_t b_varying_k_0_max__ = nT; + for (size_t j_1__ = 0; j_1__ < b_varying_j_1_max__; ++j_1__) { + for (size_t k_0__ = 0; k_0__ < b_varying_k_0_max__; ++k_0__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "b_varying" << '.' << k_0__ + 1 << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t R_j_2_max__ = (n_varying_covars * correlated_rw); + size_t R_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < R_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < R_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "R" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t Sigma_j_2_max__ = (n_varying_covars * correlated_rw); + size_t Sigma_j_1_max__ = (n_varying_covars * correlated_rw); + for (size_t j_2__ = 0; j_2__ < Sigma_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < Sigma_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "Sigma" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t eta_j_1_max__ = nT; + for (size_t j_1__ = 0; j_1__ < eta_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "eta" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + size_t X_fixed_j_2_max__ = n_fixed_covars; + size_t X_fixed_j_1_max__ = nT; + for (size_t j_2__ = 0; j_2__ < X_fixed_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < X_fixed_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "X_fixed" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + size_t X_varying_j_2_max__ = n_varying_covars; + size_t X_varying_j_1_max__ = nT; + for (size_t j_2__ = 0; j_2__ < X_varying_j_2_max__; ++j_2__) { + for (size_t j_1__ = 0; j_1__ < X_varying_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "X_varying" << '.' << j_1__ + 1 << '.' << j_2__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } + } + if (!include_gqs__) return; + size_t log_lik_j_1_max__ = N; + for (size_t j_1__ = 0; j_1__ < log_lik_j_1_max__; ++j_1__) { + param_name_stream__.str(std::string()); + param_name_stream__ << "log_lik" << '.' << j_1__ + 1; + param_names__.push_back(param_name_stream__.str()); + } + } +}; // model +} // namespace +typedef model_dlm_namespace::model_dlm stan_model; +#ifndef USING_R +stan::model::model_base& new_model( + stan::io::var_context& data_context, + unsigned int seed, + std::ostream* msg_stream) { + stan_model* m = new stan_model(data_context, seed, msg_stream); + return *m; +} +#endif +#endif diff --git a/tests/testthat.r b/tests/testthat.r new file mode 100644 index 0000000..c6b9d02 --- /dev/null +++ b/tests/testthat.r @@ -0,0 +1,4 @@ +library(testthat) +library(mvdlm) + +test_check("mvdlm") diff --git a/tests/testthat/tests.R b/tests/testthat/tests.R new file mode 100644 index 0000000..0ca8f73 --- /dev/null +++ b/tests/testthat/tests.R @@ -0,0 +1,209 @@ + +test_that("model fit with time varying formula works", { +set.seed(123) +N = 20 +data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=TRUE)) +b_1 = cumsum(rnorm(N)) +b_2 = cumsum(rnorm(N)) +data$y = data$cov1*b_1 + data$cov2*b_2 +time_varying = y ~ cov1 + cov2 +formula = NULL + +fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = FALSE, + family = c("normal"), + data = data, chains = 1, iter = 20) + +expect(class(fit$fit) == "stanfit") +}) + +test_that("model fit with normal, gamma, and lognormal family works", { + set.seed(123) + N = 20 + data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=TRUE)) + b_1 = cumsum(rnorm(N)) + b_2 = cumsum(rnorm(N)) + data$y = data$cov1*b_1 + data$cov2*b_2 + time_varying = y ~ -1 + cov1 + cov2 + formula = y ~ 1 + + fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = FALSE, + family = c("normal"), + data = data, chains = 1, iter = 20) + expect(class(fit$fit) == "stanfit") + + data$y = data$y + abs(min(data$y)) + 1 + + fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = FALSE, + family = c("gamma"), + data = data, chains = 1, iter = 20) + expect(class(fit$fit) == "stanfit") + + fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = FALSE, + family = c("lognormal"), + data = data, chains = 1, iter = 20) + expect(class(fit$fit) == "stanfit") +}) + +test_that("model fit with binomial family works", { + set.seed(123) + N = 20 + data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=TRUE)) + b_1 = cumsum(rnorm(N)) + b_2 = cumsum(rnorm(N)) + data$y = rbinom(n=nrow(data), prob=plogis(data$cov1*b_1 + data$cov2*b_2), size=1) + time_varying = y ~ -1 + cov1 + cov2 + formula = y ~ 1 + + fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = FALSE, + family = c("binomial"), + data = data, chains = 1, iter = 20) + expect(class(fit$fit) == "stanfit") +}) + +test_that("model fit with poisson and negative binomial family works", { + set.seed(123) + N = 20 + data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=TRUE)) + b_1 = cumsum(rnorm(N)) + b_2 = cumsum(rnorm(N)) + data$y = rpois(n=nrow(data), exp(data$cov1*b_1 + data$cov2*b_2)) + time_varying = y ~ -1 + cov1 + cov2 + formula = y ~ 1 + + fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = FALSE, + family = c("nbinom2"), + data = data, chains = 1, iter = 20) + expect(class(fit$fit) == "stanfit") +}) + +test_that("estimating df works", { + set.seed(123) + N = 20 + data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=TRUE)) + b_1 = cumsum(rnorm(N)) + b_2 = cumsum(rnorm(N)) + data$y = rpois(n=nrow(data), exp(data$cov1*b_1 + data$cov2*b_2)) + time_varying = y ~ -1 + cov1 + cov2 + formula = y ~ 1 + + fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + est_df = TRUE, + family = c("nbinom2"), + data = data, chains = 1, iter = 20) + expect(class(fit$fit) == "stanfit") +}) + + +test_that("uncorrelated random walk works", { + set.seed(123) + N = 20 + data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=TRUE)) + b_1 = cumsum(rnorm(N)) + b_2 = cumsum(rnorm(N)) + data$y = data$cov1*b_1 + data$cov2*b_2 + time_varying = y ~ -1 + cov1 + cov2 + formula = y ~ 1 + + fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + correlated_rw = FALSE, + family = c("normal"), + data = data, chains = 1, iter = 20) + expect(class(fit$fit) == "stanfit") +}) + +# test_that("plotting works", { +# set.seed(123) +# N = 20 +# data = data.frame("y" = runif(N), +# "cov1" = rnorm(N), +# "cov2" = rnorm(N), +# "year" = 1:N, +# "season" = sample(c("A","B"), size=N, replace=TRUE)) +# b_1 = cumsum(rnorm(N)) +# b_2 = cumsum(rnorm(N)) +# data$y = data$cov1*b_1 + data$cov2*b_2 +# time_varying = y ~ -1 + cov1 + cov2 +# formula = y ~ 1 +# +# fit <- fit_dlm(formula = formula, +# time_varying = time_varying, +# time = "year", +# family = c("normal"), +# data = data, chains = 1, iter = 20) +# +# g <- dlm_trends(fit) +# expect_equal(class(g), "list") +# expect_equal(names(g)[1], "plot") +# expect_equal(names(g)[2], "b_varying") +# expect_equal(prod(dim(g[[2]])), 200) +# }) + +test_that("missing covariates works", { + set.seed(123) + N = 20 + data = data.frame("y" = runif(N), + "cov1" = rnorm(N), + "cov2" = rnorm(N), + "year" = 1:N, + "season" = sample(c("A","B"), size=N, replace=TRUE)) + b_1 = cumsum(rnorm(N)) + b_2 = cumsum(rnorm(N)) + data$y = rpois(n=nrow(data), exp(data$cov1*b_1 + data$cov2*b_2)) + data$cov1[10] = NA + data$cov2[3] = NA + time_varying = y ~ cov1 + cov2 + formula = NULL + + fit <- fit_dlm(formula = formula, + time_varying = time_varying, + time = "year", + family = c("normal"), + data = data, chains = 1, iter = 20) + expect(class(fit$fit) == "stanfit") +}) diff --git a/vignettes/a01_overview.Rmd b/vignettes/a01_overview.Rmd new file mode 100644 index 0000000..7738c98 --- /dev/null +++ b/vignettes/a01_overview.Rmd @@ -0,0 +1,129 @@ +--- +title: "Overview of mvdlm package" +author: "Eric J. Ward" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Overview of mvdlm package} + %\VignetteEngine{knitr::rmarkdown} + \usepackage[utf8]{inputenc} +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + +### Overview + +For examples, we're going to use one of the same datasets that are widely documented in the MARSS manual. This data consists of three columns, +* year, representing the year of the observation +* logit.s, representing logit-transformed survival of Columbia River salmon +* CUI.apr, representing coastal upwelling index values in April + +```{r} +library(mvdlm) +library(MARSS) +library(ggplot2) +library(broom.mixed) +library(loo) +data(SalmonSurvCUI) +head(SalmonSurvCUI) +``` + +```{r} +g1 <- ggplot(SalmonSurvCUI, aes(year, logit.s)) + + geom_point() + + geom_line() +g1 +``` + +```{r} +g2 <- ggplot(SalmonSurvCUI, aes(year, CUI.apr)) + + geom_point() + + geom_line() +g2 +``` + +### Model 1: time varying intercept and slope + +For a first model, we'll fit the same model used in the `MARSS` manual, with a time varying intercept and time varying coefficient on CUI. We can specify these time varying effects using the `time_varying` argument. Note an intercept is not included, like with `lm`, `glm`, and similar packages this the intercept is implicitly included. Note that alternatively you could specify this formula as `time_varying = logit.s ~ 1 + CUI.apr`, where we add the extra `1` to signify the intercept. + +Like the `MARSS` example, we also standardize the covariates, + +```{r} +SalmonSurvCUI$CUI.apr = scale(SalmonSurvCUI$CUI.apr) + +fit <- fit_dlm(time_varying = logit.s ~ CUI.apr, + data = SalmonSurvCUI, + chains=1, + iter=1000) +``` + +With only 1000 iterations and 1 chain, we might not expect the model to converge (see additional guidance via Stan developers here: https://mc-stan.org/misc/warnings.html). A couple things to consider: + +* Did you get any warnings about divergent transitions after warmup? If so, try increasing the iterations / burn-in period, and number of chains. It's also worth increasing the value of `adapt_delta`. (this will slow the sampling down a little). If you're still getting these warnings, the model may be mis-specified or data not informative. + +```{r eval=FALSE} +fit <- fit_dlm(time_varying = logit.s ~ CUI.apr, + data = SalmonSurvCUI, + chains=1, + iter=1000, + control = list(adapt_delta=0.99)) +``` + +* Did you get a warning about the maximum tree depth? If so, you can increase the maximum tree (`max_treedepth`) depth with the following + +```{r eval=FALSE} +fit <- fit_dlm(time_varying = logit.s ~ CUI.apr, + data = SalmonSurvCUI, + chains=1, + iter=1000, + control = list(max_treedepth=15)) +``` + +We can extract tidied versions of any of the parameters with + +```{r} +broom.mixed::tidy(fit$fit) +``` + +We also have a helper function for extracting and visualizing trends for time varying parameters. + +```{r} +dlm_trends(fit) +``` + +This function returns a plot and the values used to make the plot (`b_varying`) + +### Model 2: time varying intercept and constant slope + +As a second example, we could fit a model with a constant effect of CUI, but a time varying slope. The `fit_dlm` function has two formula parameters, `formula` for static effects, and `time_varying` for time varying ones. This model is specified as + +```{r eval=FALSE} +fit <- fit_dlm(time_varying = logit.s ~ 1, + formula = logit.s ~ CUI.apr, + data = SalmonSurvCUI, + chains=1, + iter=1000) +``` + +### Model 3: constant intercept and time varying slope + +We could do the same with a model that had a time varying effect of CUI, but a time constant slope. +```{r eval=FALSE} +fit <- fit_dlm(time_varying = logit.s ~ CUI.apr, + formula = logit.s ~ 1, + data = SalmonSurvCUI, + chains=1, + iter=1000) +``` + +### Comparing models + +All three of the above formulations of the DLM can be compared with the `loo` package, and statistics such as LOOIC can be easily calculated. For example, + +```{r eval=FALSE} +library(loo) +loo::loo(fit$fit) +``` +