| Title: | Reproducible Ecological Generalized Linear Mixed Model Pipelines |
|---|---|
| Description: | Fits and compares generalized linear mixed models for multiple ecological responses and environmental predictors. The package supports additive and temporal-interaction candidate models, AICc model selection, likelihood-ratio tests, coefficient extraction, Nakagawa R-squared, simulation-based diagnostics, figures, and spreadsheet exports. Model selection follows Burnham and Anderson (2002, ISBN:9780387953649); marginal and conditional R-squared follow Nakagawa and Schielzeth (2013) <doi:10.1111/j.2041-210x.2012.00261.x>. |
| Authors: | André Felipe Carneiro dos Santos [aut, cre] (ORCID: <https://orcid.org/0009-0000-8596-1975>), Bruna Martins Bezerra [aut] (ORCID: <https://orcid.org/0000-0003-3039-121X>), Bárbara Lins Caldas de Moraes [aut] (ORCID: <https://orcid.org/0000-0002-1804-9828>) |
| Maintainer: | André Felipe Carneiro dos Santos <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.4 |
| Built: | 2026-10-04 13:30:10 UTC |
| Source: | https://github.com/andre-fcsantos/ecoglmm |
Fits, compares, diagnoses, plots, and exports candidate generalized linear mixed models for multiple ecological responses and environmental predictors.
Keep proportions inside the open interval (0, 1)
adjust_beta(x, epsilon = 0.001)adjust_beta(x, epsilon = 0.001)
x |
Numeric vector. |
epsilon |
Small boundary value. |
A numeric vector with boundary values adjusted.
adjust_beta(c(0, 0.25, 0.5, 0.75, 1))adjust_beta(c(0, 0.25, 0.5, 0.75, 1))
Compare a candidate set using corrected Akaike information criterion
compare_models(models, competitive_delta = 2)compare_models(models, competitive_delta = 2)
models |
Named list of fitted models. |
competitive_delta |
Maximum delta AICc defining competitive models. |
Model-selection data frame.
dat <- data.frame( y = c(1.0, 1.3, 1.2, 1.7, 1.5, 2.0, 1.8, 2.2, 2.1, 2.5, 2.4, 2.8), x = rep(1:6, 2), period = factor(rep(c("early", "late"), each = 6)) ) models <- list( x_Add = stats::lm(y ~ x + period, data = dat), x_Int = stats::lm(y ~ x * period, data = dat) ) compare_models(models)dat <- data.frame( y = c(1.0, 1.3, 1.2, 1.7, 1.5, 2.0, 1.8, 2.2, 2.1, 2.5, 2.4, 2.8), x = rep(1:6, 2), period = factor(rep(c("early", "late"), each = 6)) ) models <- list( x_Add = stats::lm(y ~ x + period, data = dat), x_Int = stats::lm(y ~ x * period, data = dat) ) compare_models(models)
Run DHARMa diagnostics for selected models
diagnose_models(object, nsim = 1000, seed = NULL)diagnose_models(object, nsim = 1000, seed = NULL)
object |
An 'ecoglmm_fit' object. |
nsim |
Number of simulations. |
seed |
Optional random seed. |
List containing a summary table and simulated residual objects.
set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) diagnostics <- diagnose_models(fit, nsim = 20, seed = 1) diagnostics$summaryset.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) diagnostics <- diagnose_models(fit, nsim = 20, seed = 1) diagnostics$summary
Export ecoGLMM results to an output directory
export_ecoglmm( object, path, diagnostics = NULL, figures = TRUE, diagnostic_pdf = TRUE )export_ecoglmm( object, path, diagnostics = NULL, figures = TRUE, diagnostic_pdf = TRUE )
object |
An 'ecoglmm_fit' object. |
path |
Output directory. |
diagnostics |
Optional result returned by [diagnose_models()]. |
figures |
Save effect and selection figures. |
diagnostic_pdf |
Save a multi-page PDF containing the DHARMa plot and
a diagnostic summary for each selected response model. The PDF is created
only when |
Invisibly returns generated file paths.
set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) output <- file.path(tempdir(), "ecoGLMM-example") files <- export_ecoglmm(fit, path = output, figures = FALSE) basename(files)set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) output <- file.path(tempdir(), "ecoGLMM-example") files <- export_ecoglmm(fit, path = output, figures = FALSE) basename(files)
Extract coefficients and model-level statistics
extract_results(models, selections, conf_level = 0.95)extract_results(models, selections, conf_level = 0.95)
models |
Named list of selected models. |
selections |
Named list of model-selection tables. |
conf_level |
Confidence level for Wald intervals. |
Tidy coefficient data frame.
set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) extract_results(fit$best_models, fit$selection)set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) extract_results(fit$best_models, fit$selection)
Plot coefficients and confidence intervals
plot_coefficients(object, include_intercept = FALSE)plot_coefficients(object, include_intercept = FALSE)
object |
An 'ecoglmm_fit' object. |
include_intercept |
Include intercept terms. |
A faceted ggplot object.
set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) plot_coefficients(fit)set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) plot_coefficients(fit)
Plot the marginal effect of a selected model
plot_effect(object, response, show_observed = TRUE)plot_effect(object, response, show_observed = TRUE)
object |
An 'ecoglmm_fit' object. |
response |
Response name. |
show_observed |
Add observed values. |
A ggplot object.
set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) plot_effect(fit, "index", show_observed = FALSE)set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) plot_effect(fit, "index", show_observed = FALSE)
Plot model-selection results
plot_selection(object, response, metric = c("delta", "weight"))plot_selection(object, response, metric = c("delta", "weight"))
object |
An 'ecoglmm_fit' object. |
response |
Response name. |
metric |
Either 'delta' or 'weight'. |
A ggplot object.
set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) plot_selection(fit, "index")set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) plot_selection(fit, "index")
Prepare common acoustic-index transformations
prepare_acoustic_indices( data, ndsi = "NDSI", beta_responses = c("AEI", "ACT"), ndsi_output = "NDSI_beta", epsilon = 0.001 )prepare_acoustic_indices( data, ndsi = "NDSI", beta_responses = c("AEI", "ACT"), ndsi_output = "NDSI_beta", epsilon = 0.001 )
data |
A data frame. |
ndsi |
Name of the NDSI column, or 'NULL'. |
beta_responses |
Names of responses already bounded by zero and one. |
ndsi_output |
Name assigned to transformed NDSI. |
epsilon |
Boundary adjustment used by [adjust_beta()]. |
A modified data frame.
indices <- data.frame( NDSI = c(-1, 0, 1), AEI = c(0, 0.5, 1), ACT = c(0.2, 0.6, 0.9) ) prepare_acoustic_indices(indices)indices <- data.frame( NDSI = c(-1, 0, 1), AEI = c(0, 0.5, 1), ACT = c(0.2, 0.6, 0.9) ) prepare_acoustic_indices(indices)
Validate and prepare ecological modelling data
prepare_ecodata( data, config, predictors, period, group, period_levels = NULL, standardize = TRUE, complete_cases = TRUE )prepare_ecodata( data, config, predictors, period, group, period_levels = NULL, standardize = TRUE, complete_cases = TRUE )
data |
A data frame containing responses, predictors and grouping data. |
config |
Response configuration with 'response' and 'family' columns. |
predictors |
Environmental predictor names. |
period |
Temporal-factor column. |
group |
Random-intercept grouping column. |
period_levels |
Optional ordered levels for the temporal factor. |
standardize |
Logical; standardize numeric predictors using z-scores. |
complete_cases |
Logical; use one shared complete-case dataset for all candidate models. This should normally remain 'TRUE' for valid AICc comparisons. |
Prepared data with preparation metadata stored as attributes.
dat <- data.frame( response = c(1.1, 1.4, 1.2, 1.8, 1.5, 2), forest = c(10, 20, 30, 40, 50, 60), period = rep(c("early", "late"), 3), site = rep(c("a", "b", "c"), each = 2) ) config <- data.frame(response = "response", family = "gaussian") prepared <- prepare_ecodata( dat, config, predictors = "forest", period = "period", group = "site" ) head(prepared)dat <- data.frame( response = c(1.1, 1.4, 1.2, 1.8, 1.5, 2), forest = c(10, 20, 30, 40, 50, 60), period = rep(c("early", "late"), 3), site = rep(c("a", "b", "c"), each = 2) ) config <- data.frame(response = "response", family = "gaussian") prepared <- prepare_ecodata( dat, config, predictors = "forest", period = "period", group = "site" ) head(prepared)
Run an ecological GLMM candidate-model pipeline
run_ecoglmm( data, config, predictors, period, group, period_levels = NULL, standardize = TRUE, complete_cases = TRUE, include_additive = TRUE, include_interactions = TRUE, competitive_delta = 2, control = NULL )run_ecoglmm( data, config, predictors, period, group, period_levels = NULL, standardize = TRUE, complete_cases = TRUE, include_additive = TRUE, include_interactions = TRUE, competitive_delta = 2, control = NULL )
data |
Prepared or raw data frame. |
config |
Data frame with 'response', 'family', and optional 'label'. |
predictors |
Environmental predictor names. |
period |
Temporal-factor column name. |
group |
Random-intercept grouping column name. |
period_levels |
Optional order of temporal levels. |
standardize |
Standardize predictors with z-scores. |
complete_cases |
Use one common complete-case dataset. |
include_additive |
Include predictor + period models. |
include_interactions |
Include predictor * period models. |
competitive_delta |
Delta AICc threshold. |
control |
Optional [glmmTMB::glmmTMBControl()] object. |
An object of class 'ecoglmm_fit'.
set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) fit summary(fit)set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = FALSE ) fit summary(fit)
Likelihood-ratio tests for additive versus interaction models
test_interactions(models, predictors)test_interactions(models, predictors)
models |
Named candidate-model list. |
predictors |
Predictor names. |
Data frame of likelihood-ratio tests.
set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = TRUE ) test_interactions(fit$models$index, predictors = "forest")set.seed(1) example_data <- expand.grid( site = paste0("s", 1:6), period = c("early", "late"), replicate = 1:3, stringsAsFactors = FALSE ) example_data$forest <- runif(nrow(example_data)) site_effect <- setNames(rnorm(6, sd = 0.3), paste0("s", 1:6)) example_data$index <- 1 + 0.8 * example_data$forest + 0.4 * (example_data$period == "late") + site_effect[example_data$site] + rnorm(nrow(example_data), sd = 0.15) config <- data.frame(response = "index", family = "gaussian") fit <- run_ecoglmm( data = example_data, config = config, predictors = "forest", period = "period", group = "site", include_interactions = TRUE ) test_interactions(fit$models$index, predictors = "forest")