--- title: "Effect modification" output: rmarkdown::html_vignette: toc: true vignette: > %\VignetteIndexEntry{Effect modification} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", message = FALSE ) ``` ```{r setup} library(ameras) data(data, package = "ameras") ``` # Introduction Effect modification is specified inside `dose()` with the `modifier` argument. Formula modifiers can be binary numeric/logical variables or factors. Character variables are not accepted as modifiers; convert them to factors first so the level order is explicit. There are two useful ways to code effect modification: - `modifier = ~ M` uses reference-plus-contrast coding. - `modifier = ~ 0 + M` or `modifier = ~ M - 1` uses subgroup-specific coding. These are reparameterizations of the same model. They give the same fitted likelihood when the same model and data are used, but the coefficients answer different questions directly. # Reference-plus-contrast coding Reference-plus-contrast coding is the default formula-modifier coding. For a binary modifier `M1`, the coefficient named `dose` is the dose effect in the reference group, and `dose:M1` is the difference between the non-reference group and the reference group. ```{r contrast-fit} fit_contrast <- ameras( Y.gaussian ~ dose(V1:V10, modifier = ~ M1) + X1 + X2, data = data, family = "gaussian", methods = "RC" ) coef(fit_contrast) ``` This coding is convenient when the effect-modification contrast is the main quantity of interest. # Subgroup-specific coding Subgroup-specific coding reports one dose-effect parameter per subgroup. For the same binary modifier `M1`, the coefficient names are `dose[M1=0]` and `dose[M1=1]`. ```{r subgroup-fit} fit_subgroup <- ameras( Y.gaussian ~ dose(V1:V10, modifier = ~ 0 + M1) + X1 + X2, data = data, family = "gaussian", methods = "RC" ) coef(fit_subgroup) ``` The two codings are equivalent. The non-reference subgroup effect is the reference effect plus the contrast: ```{r coding-equivalence} contrast_coef <- fit_contrast$RC$coefficients subgroup_coef <- fit_subgroup$RC$coefficients data.frame( term = c("reference group", "non-reference group"), from_contrast = c( contrast_coef["dose"], contrast_coef["dose"] + contrast_coef["dose:M1"] ), from_subgroup = c( subgroup_coef["dose[M1=0]"], subgroup_coef["dose[M1=1]"] ), row.names = NULL ) ``` Subgroup-specific coding is usually the cleaner choice when subgroup-specific effect estimates and confidence intervals are the main goal. For linear ERR and linear-exponential models, it can also be more numerically robust because default bounds are applied directly to each subgroup dose-effect parameter. With reference-plus-contrast coding, contrast parameters are not bounded by the default transformation. # Factor modifiers Factor modifiers use the existing level order of the factor. The first level is the reference level. ```{r factor-setup} data$M_factor <- factor( ifelse(data$M1 == 0, "unexposed modifier group", "modifier group"), levels = c("unexposed modifier group", "modifier group") ) ``` With `modifier = ~ M_factor`, ameras reports contrast terms for the non-reference levels. ```{r factor-contrast} fit_factor_contrast <- ameras( Y.gaussian ~ dose(V1:V10, modifier = ~ M_factor) + X1 + X2, data = data, family = "gaussian", methods = "RC" ) coef(fit_factor_contrast) ``` With `modifier = ~ 0 + M_factor`, ameras reports subgroup-specific effects for all levels. ```{r factor-subgroup} fit_factor_subgroup <- ameras( Y.gaussian ~ dose(V1:V10, modifier = ~ 0 + M_factor) + X1 + X2, data = data, family = "gaussian", methods = "RC" ) coef(fit_factor_subgroup) ``` Multi-level factors are supported. With reference-plus-contrast coding, ameras reports one contrast for each non-reference level. With subgroup-specific coding, ameras reports one dose-effect parameter for each factor level. ```{r three-level-factor} data$M3 <- factor( rep(c("low", "middle", "high"), length.out = nrow(data)), levels = c("low", "middle", "high") ) fit_three_level <- ameras( Y.gaussian ~ dose(V1:V10, modifier = ~ 0 + M3) + X1 + X2, data = data, family = "gaussian", methods = "RC" ) coef(fit_three_level) ``` # Confidence intervals For subgroup-specific confidence intervals, fit the model using subgroup-specific coding and then call `confint()` as usual. For `RC`, `ERC`, and `MCML`, profile likelihood intervals treat subgroup effects as ordinary coefficient rows. ```{r subgroup-ci, eval = FALSE} fit_subgroup <- confint( fit_subgroup, type = "proflik", parm = "dose" ) summary(fit_subgroup) ``` For `FMA` and `BMA`, sample-based confidence or credible intervals are computed from the sampled coefficients. When subgroup-specific coding is used, BMA priors and MCMC sampling remain on the internal reference-plus-contrast scale, but stored samples, summaries, diagnostics, trace plots, and sample-based intervals are reported on the subgroup-specific scale. # Choosing a coding Use reference-plus-contrast coding when the contrast itself is the main estimand. Use subgroup-specific coding when subgroup effects are the main estimands, when subgroup-specific profile likelihood intervals are desired, or when ERR/LINEXP optimization is sensitive to the unbounded contrast parameterization. Testing whether effect modification improves the model is a model-comparison question. Fit a model without the modifier and a model with the modifier, then compare the fitted likelihoods using the appropriate degrees of freedom. `dose_lrt()` tests dose-related parameters, but its global dose test is not the same as a test for effect modification.