## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4.1, dpi = 144 ) if (!"package:drmTMB" %in% search()) { library(drmTMB) } location_scale_theme <- function() { ggplot2::theme_minimal(base_size = 11) + ggplot2::theme( panel.grid.minor = ggplot2::element_blank(), panel.grid.major.x = ggplot2::element_line( colour = "grey90", linewidth = 0.3 ), panel.grid.major.y = ggplot2::element_line( colour = "grey87", linewidth = 0.35 ), axis.title = ggplot2::element_text(colour = "grey15"), axis.text = ggplot2::element_text(colour = "grey25"), plot.title = ggplot2::element_text( face = "bold", colour = "grey10", margin = ggplot2::margin(b = 4) ), plot.subtitle = ggplot2::element_text( colour = "grey30", margin = ggplot2::margin(b = 8) ), legend.position = "bottom", legend.title = ggplot2::element_text(colour = "grey20") ) } location_scale_habitat_scales <- function() { list( ggplot2::scale_colour_manual( values = c("forest" = "#0072B2", "grassland" = "#009E73") ), ggplot2::scale_fill_manual( values = c("forest" = "#0072B2", "grassland" = "#009E73") ) ) } ## ----location-scale-simulate-------------------------------------------------- set.seed(42) n <- 240 dat <- data.frame( habitat = factor(rep(c("forest", "grassland"), each = n / 2)), temperature = rnorm(n) ) mu <- 8 + 1.2 * (dat$habitat == "grassland") + 0.6 * dat$temperature sigma_true <- exp(log(0.6) + 0.55 * (dat$habitat == "grassland")) dat$growth <- rnorm(n, mean = mu, sd = sigma_true) ## ----location-scale-fit------------------------------------------------------- fit_growth <- drmTMB( drm_formula(growth ~ habitat + temperature, sigma ~ habitat), family = gaussian(), data = dat ) ## ----location-scale-check----------------------------------------------------- check_drm(fit_growth) ## ----location-scale-profile-targets------------------------------------------- profile_targets(fit_growth)[ , c("parm", "estimate", "profile_ready", "profile_note") ] ## ----location-scale-summary--------------------------------------------------- summary(fit_growth) ## ----location-scale-interpret-sigma------------------------------------------- sigma_habitat <- coef(fit_growth, "sigma")["habitatgrassland"] data.frame( coefficient = sigma_habitat, residual_sd_ratio = exp(sigma_habitat), residual_variance_ratio = exp(2 * sigma_habitat) ) ## ----location-scale-response-table-------------------------------------------- newdat <- data.frame( habitat = factor(c("forest", "grassland"), levels = levels(dat$habitat)), temperature = 0 ) growth_report <- data.frame( habitat = newdat$habitat, fitted_mean_growth = predict(fit_growth, newdata = newdat, dpar = "mu"), fitted_residual_sd = predict(fit_growth, newdata = newdat, dpar = "sigma") ) growth_report$fitted_residual_variance <- growth_report$fitted_residual_sd^2 growth_report ## ----location-scale-growth-figure, fig.cap = "Raw growth observations and fitted response-scale `mu` surfaces for the Gaussian location-scale example; ribbons are 95% Wald confidence bands from `predict_parameters()`.", fig.alt = "Scatterplot of simulated growth over temperature for forest and grassland habitats, with fitted mean growth lines and 95 percent Wald confidence bands for each habitat."---- growth_mu_grid <- prediction_grid( fit_growth, focal = c("temperature", "habitat"), at = list( temperature = seq( min(dat$temperature), max(dat$temperature), length.out = 80 ) ) ) growth_mu_surface <- predict_parameters( fit_growth, newdata = growth_mu_grid, dpar = "mu", conf.int = TRUE ) unique(growth_mu_surface[, c( "dpar", "conf.status", "interval_source", "conf.level" )]) if (requireNamespace("ggplot2", quietly = TRUE)) { ggplot2::ggplot( dat, ggplot2::aes(x = temperature, y = growth, colour = habitat) ) + ggplot2::geom_point(alpha = 0.38, size = 1.25) + ggplot2::geom_ribbon( data = growth_mu_surface, ggplot2::aes( x = temperature, ymin = conf.low, ymax = conf.high, fill = habitat ), inherit.aes = FALSE, alpha = 0.18, colour = NA ) + ggplot2::geom_line( data = growth_mu_surface, ggplot2::aes(y = estimate), linewidth = 0.85 ) + location_scale_habitat_scales() + ggplot2::labs( title = "Mean growth and observed scatter", subtitle = "Points are raw growth; ribbons are 95% Wald bands for mu", x = "Temperature", y = "Growth", colour = "Habitat", fill = "Habitat" ) + location_scale_theme() + ggplot2::guides(fill = "none") } ## ----location-scale-sigma-contrast-figure, fig.width = 5.8, fig.height = 2.6, fig.cap = "Fitted residual standard deviations by habitat at average temperature; horizontal intervals are 95% Wald confidence intervals requested from `predict_parameters()`.", fig.alt = "Horizontal point interval plot comparing fitted residual standard deviation for forest and grassland habitats at temperature zero, with 95 percent Wald confidence intervals."---- growth_sigma_grid <- prediction_grid( fit_growth, focal = "habitat", condition = list(temperature = 0) ) growth_sigma_surface <- predict_parameters( fit_growth, newdata = growth_sigma_grid, dpar = "sigma", conf.int = TRUE ) unique(growth_sigma_surface[, c( "dpar", "conf.status", "interval_source", "conf.level" )]) if (requireNamespace("ggplot2", quietly = TRUE)) { ggplot2::ggplot( growth_sigma_surface, ggplot2::aes(x = estimate, y = habitat, colour = habitat) ) + ggplot2::geom_segment( ggplot2::aes(x = conf.low, xend = conf.high, yend = habitat), linewidth = 0.8 ) + ggplot2::geom_point(size = 2.8) + location_scale_habitat_scales() + ggplot2::labs( title = "Residual SD differs by habitat", subtitle = "Points are fitted sigma values; bars are 95% Wald intervals", x = "Fitted residual SD (sigma)", y = NULL, colour = "Habitat" ) + location_scale_theme() + ggplot2::guides(colour = "none") } ## ----location-scale-translation-table----------------------------------------- growth_translation <- data.frame( model_piece = c( "fixed mean slope", "fixed residual-SD contrast", "fixed residual-variance contrast" ), fitted_term = c( "mu:temperature", "exp(sigma:habitatgrassland)", "exp(2 * sigma:habitatgrassland)" ), response_scale_value = c( unname(coef(fit_growth, "mu")["temperature"]), unname(exp(sigma_habitat)), unname(exp(2 * sigma_habitat)) ), interpretation = c( "mean growth change per one-unit temperature increase", "grassland residual SD divided by forest residual SD", "grassland residual variance divided by forest residual variance" ) ) growth_translation$response_scale_value <- round(growth_translation$response_scale_value, 3) growth_translation