The goal of pmxhelpr is to make pharmacometrics workflows more standardized, efficient, and reproducible. This package provides helper and wrapper functions for common steps in the modeling analysis workflow, outside of model parameter estimation. Currently, workflows cover key steps in exploratory data analysis, model evaluation, and forest plot model applications.
Documentation
Full narrative documentation, including worked examples for every plotting workflow, lives on the pmxhelpr website. Start with the articles:
- Getting Started with pmxhelpr — a lean tour of every core workflow in one sitting.
- Exploratory Analyses of PK and PK/PD Data
- Dose-Proportionality Workflow
- Goodness-of-Fit Diagnostics
- Visual Predictive Check Workflow
- Forest Plot Workflow
- Plot Styling and Aesthetics
Installation
pmxhelpr and its styling dependency ggstylekit are distributed through the PRISM package repository rather than CRAN. Each release of each package has its own PRISM repository, so declare both alongside a CRAN mirror for the remaining dependencies.
The recommended way to install pmxhelpr is with rv. Add the two PRISM repositories and pmxhelpr to your project’s rproject.toml, then run rv sync:
repositories = [
{ alias = "CRAN", url = "https://packagemanager.posit.co/cran/latest" },
{ alias = "pmxhelpr", url = "https://prism.dev.a2-ai.cloud/rpkgs/pmxhelpr/0.7.0/" },
{ alias = "ggstylekit", url = "https://prism.dev.a2-ai.cloud/rpkgs/ggstylekit/0.4.1/" }
]
dependencies = [
"pmxhelpr"
]Alternatively, install from the same repositories with install.packages():
install.packages("pmxhelpr",
repos = c("https://prism.dev.a2-ai.cloud/rpkgs/pmxhelpr/0.7.0",
"https://prism.dev.a2-ai.cloud/rpkgs/ggstylekit/0.4.1",
getOption("repos")))To install a development version or another tagged release from GitHub, install ggstylekit from PRISM first, then use devtools:
# install.packages("devtools")
install.packages("ggstylekit",
repos = c("https://prism.dev.a2-ai.cloud/rpkgs/ggstylekit/0.4.1",
getOption("repos")))
devtools::install_github("ryancrass/pmxhelpr@v0.7.0")The README examples use a package from Suggests that isn’t installed automatically:
install.packages("patchwork")Function Naming Conventions
Exported functions follow a ReturnType_Purpose naming convention where the prefix indicates what the function returns:
-
plot_*— returns aggplotobject -
df_*— returns adata.frame, or apmx_statscontainer ($stats,$obs,$config) for the stats functions -
var_*— returns a vector (vectorized helpers for use insidemutate) -
style_*— returns aggstylekit::style_spec(plot-family style preset)
Exploratory Data Analysis
- Longitudinal PK and PK/PD Analysis:
-
plot_dvtime()— dependent variable versus time (e.g., concentration-time profiles) -
plot_dvconc()— dependent variable versus a continuous independent variable (e.g., response vs concentration)
-
- Dose Proportionality:
-
df_doseprop()— log-log regression parameters for multiple exposure metrics versus dose -
plot_doseprop()— log-log regression plots of exposure metric(s) versus dose
-
Model Evaluation
- Overlay Goodness-of-Fit Diagnostics:
-
plot_gof()— observed, population-, and individual-predicted values overlaid versus time
-
- Visual Predictive Check (VPC):
-
df_mrgsim_replicate()— simulated replicates of an input dataset viamrgsolve -
df_vpcstats()— VPC summary statistics -
plot_vpc_cont()— VPC plot for continuous data range from simulated data with exact time bins -
plot_vpc_cens()— VPC plot for censored data range from simulated data with exact time bins -
plot_vpc_legend()— legend for a VPC plot
-
Model Application
- Forest Plots:
-
df_forest_preprocess()— Reshape replicate simulation output into forest plot draws -
df_forest()— Forest plot summary statistics -
plot_forest()— Forest plot of covariate impact
-
Styling
Plot aesthetics are controlled with ggstylekit. Each plot function has a corresponding style_*() preset that returns a ggstylekit::style_spec() pre-filled with the plot family defaults:
-
style_dvtime(),style_dvconc(),style_doseprop(),style_gof(),style_vpc(),style_forest()— pass one to thestyleargument of the matching plot function -
plot_vpc_shown()/plot_gof_shown()— control which VPC / GOF layers are visible via theshownargument
Styling is based on maps for plot aesthetics, which are keyed by roles in the output plot (e.g. obs_point, cent_line, cent_errorbar, ref_line, loq_line). The per-series maps (colors, shapes, sizes, linetypes, linewidths, alphas) are keyed by role, and only the roles specified override the defaults.
Additional variables in the dataset can be surfaced after the fact with reveal(), legends are described with legend_spec(), and styled plots are assembled with combine_styled_plots().
S3 Class System
pmxhelpr returns class-tagged objects for stats outputs, with predicates and print()/summary() methods for interactive inspection and programmatic validation.
- Stats classes —
df_vpcstats(),df_doseprop(), anddf_forest()returnpmx_statscontainers of classvpc_stats,doseprop_stats, andforest_stats(stats,obs, andconfigslots). Each carriesprint(),summary(), andas.data.frame()methods plus a predicate (is_vpc_stats(),is_doseprop_stats(),is_forest_stats()). - Dual-mode plotting —
plot_vpc_cont(),plot_vpc_cens(),plot_doseprop(), andplot_forest()accept either raw input data or a precomputed stats object. The precomputed path skips the summarization / regression refit, enabling compute-once / replot-many workflows (e.g. flippingpcvpc = TRUE/FALSE, varyingstyle, trying differentmin_bin_count, or switching the forestmetric/ref_layout). The lower-level renderersplot_build_vpc()/plot_build_doseprop()/plot_build_forest()are exported for custom workflows that produce class-compatible objects outsidepmxhelpr.
pmxhelpr returns a class tagged object for VPC plot outputs to warn users via the +.pmx_vpc_plot method when facet_*() layers are added outside the returned object directing users to the correct stratification method using the strat_var argument.
See the Plot Styling and Aesthetics and VPC / Dose-Proportionality / Forest Plot workflow articles for worked examples.
Vectorized Helpers
-
var_addn()— factor labels with counts of unique identifiers per group -
var_predcorr()— prediction-corrected values -
var_dosenorm()— dose-normalized values
mrgsolve Wrappers
-
model_mread_load()— reads internal package model files returning anmrgmodobject -
df_mrgsim_replicate()— replicates input data via simulation returning adata.frame -
df_mrgsim_addpred()— adds population model predictions (PRED) to the returneddata.frame
Internal Datasets
-
data_sad— single ascending dose (SAD) study with parallel food effect cohort formatted for NLME modeling -
data_sad_nca— PK parameters derived using non-compartmental analysis (NCA) -
data_sad_pkfit—data_sadwith individual (IPRED) and population (PRED) PK model predictions -
data_sad_pkforest_sim—data_sadPK model replicate simulation output: exposure metrics across covariate scenarios, one row per scenario per replicate -
data_sad_pkforest— long-format replicate draws of absolute and test/reference ratio exposure metrics for a forest plot
Note on bundled data. data_sad and data_sad_pkfit use ODV (original DV), to note that it is provided in original units from the source data. Functions like plot_dvtime() default dv_var = DV to match the standard NONMEM convention; when running examples on the bundled data, one may derive a variable DV or pass the argument dv_var = "ODV" (as every example below does).
Example Exploratory Data Analysis Workflow
This is a basic example which illustrates a simple exploratory data analysis workflow using pmxhelpr:
library(pmxhelpr)
library(dplyr)
library(ggplot2)
#Read internal analysis-ready dataset for an example Phase 1 study
glimpse(data_sad)
#Pre-process data for plotting
data <- data_sad %>%
mutate(Food = ifelse(FOOD == 1, "Fed", "Fasted"),
DoseFood = paste(DOSE,"mg x1", Food),
Regimen = var_addn(DoseFood, ID))
#Plot drug concentration-time
plot_dvtime(data = filter(data, CMT == 2), dv_var = "ODV", cent = "mean_sdl",
col_var = "Regimen", log_y = TRUE, show_obs = FALSE) +
labs(y = "Concentration (ng/mL)")
#Plot response versus concentration
plot_dvconc(data = filter(data, CMT == 3), dv_var = "CFB", ref = 0,
col_var = "Regimen", loess = TRUE, linear = TRUE) +
labs(y = "Response (% Change)")
#Assess dose proportionality in the fasted state
glimpse(data_sad_nca)
data_sad_nca_part1 <- filter(data_sad_nca, PART == "Part 1-SAD")
#Tabulated dose-proportionality
table <- df_doseprop(data_sad_nca_part1, metrics = c("aucinf.obs", "cmax"))
table
#Visualize dose-proportionality
plot_doseprop(table)
plot_doseprop(data_sad_nca_part1, metrics = c("aucinf.obs", "cmax"))Example Population Overlay Goodness-of-Fit Plot Workflow
This is a basic example which illustrates a simple model diagnostic workflow using pmxhelpr:
library(pmxhelpr)
library(dplyr)
library(ggplot2)
library(mrgsolve)
library(patchwork)
library(withr)
##Pre-process Data for Plotting
data <- data_sad_pkfit %>%
mutate(Food = ifelse(FOOD == 1, "Fed", "Fasted"),
DoseFood = paste(DOSE,"mg x1", Food),
Regimen = var_addn(DoseFood, ID))
##Generate Population Overlay Goodness-of-fit Fit Plots by Food Status
plot_gof(data = data, dv_var = "ODV", dosenorm = TRUE) +
facet_wrap(~Food) +
labs(y = "Dose-normalized Conc. (ng/mL/mg)")
plot_gof(data = data, dv_var = "ODV", log_y = TRUE) +
facet_wrap(~Regimen) +
labs(y = "Concentration (ng/mL)")Example Visual Predictive Check Analysis Workflow
This is a basic example which illustrates a simple VPC workflow using pmxhelpr:
library(pmxhelpr)
library(dplyr)
library(ggplot2)
library(mrgsolve)
library(patchwork)
library(withr)
#Read internal mrgsolve model file
model <- model_mread_load("pkmodel")
#Process Data
data <- data_sad %>%
filter(CMT %in% c(1, 2)) %>%
mutate(Food = ifelse(FOOD == 1, "Fed", "Fasted")) %>%
mutate(Food = var_addn(Food, ID))
#Simulated replicates of the dataset using mrgsim
#The input `dv_var` is preserved in the output as `OBSDV` (observed) and the
#simulated values are written to `SIMDV` --- these are the columns `plot_vpc_cont()` reads.
#Pass any input columns you want carried to the output via `carry_out` (numeric)
#and `recover` (character / factor), which flow through to `mrgsolve::mrgsim_df()`.
simout <- df_mrgsim_replicate(data = data, model = model, replicates = 100,
dv_var = "ODV",
carry_out = c("DOSE", "FOOD", "BLQ", "LLOQ"),
recover = c("PART", "Food"))
glimpse(simout)
#Plot output in a Censored Visual Predictive Check (VPC)
plot_obj_cens <- plot_vpc_cens(
data = simout,
strat_var = "DOSE"
) +
scale_x_continuous(breaks = c(0,24,72,120,168)) +
labs(y = "Proportion BLQ", x = "Time (hours)")
plot_obj_cens
#Add Legend
shown_cens <- plot_vpc_shown(obs_pi_line = FALSE, sim_pi_ci = FALSE, obs_point = FALSE)
plot_obj_cens_leg <- plot_vpc_legend(shown = shown_cens, type = "cens")
plot_obj_cens_leg
plot_obj_cens_wleg <- plot_obj_cens + plot_obj_cens_leg + plot_layout(heights = c(2,1))
plot_obj_cens_wleg
#Plot output in a Prediction-corrected Visual Predictive Check (VPC)
#Exact nominal time bins present in data_sad ("NTIME") are used to plot summary statistics
#Actual time ("TIME") is used to plot observed data points (prediction-corrected if pcvpc=TRUE)
plot_obj_food <- plot_vpc_cont(
data = simout,
strat_var = "Food",
pcvpc = TRUE
) +
scale_x_continuous(breaks = c(0,24,72,120,168)) +
scale_y_log10(guide = "axis_logticks") +
labs(y = "Pred-corrected Conc. (ng/mL)", x = "Time (hours)")
plot_obj_food
#Add Legend
plot_obj_leg <- plot_vpc_legend()
plot_obj_leg
plot_obj_food_wleg <- plot_obj_food + plot_obj_leg + plot_layout(heights = c(2,1))
plot_obj_food_wlegExample Forest Plot Workflow
This is a basic example which illustrates a forest plot workflow using pmxhelpr:
library(pmxhelpr)
library(dplyr)
library(ggplot2)
#Read View Internal Datasets
glimpse(data_sad_pkforest)
#Generate the summary dataset using df_forest()
forest_obj <- df_forest(data_sad_pkforest,
cov_level_ref = c(FOOD = "Fasted", WTBL = "70 kg"))
#Consume the summary dataset to generate the Forest Plot using plot_forest()
plot_forest(forest_obj,
metric = "AUCRATIO",
ref_band = c(0.8, 1.25)) +
scale_x_log10(limits = c(0.5, 5),
breaks = c(0.5, 0.8, 1, 1.25, 2, 3, 4, 5)) +
labs(subtitle = "Ratio (90% CI)")