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 and model evaluation.
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
- Plot Styling and Aesthetics
Installation
pmxhelpr depends on ggstylekit, which is distributed through the PRISM package repository rather than CRAN, so the repository must be declared alongside the pmxhelpr release.
The recommended way to install pmxhelpr is with rv. Add the ggstylekit PRISM repository and the most recent tagged release of pmxhelpr to your project’s rproject.toml, then run rv sync:
repositories = [
{ alias = "CRAN", url = "https://packagemanager.posit.co/cran/latest" },
{ alias = "ggstylekit", url = "https://prism.dev.a2-ai.cloud/rpkgs/ggstylekit/0.4.0/" }
]
dependencies = [
{ name = "pmxhelpr", git = "https://github.com/ryancrass/pmxhelpr.git", tag = "v0.6.0" }
]Alternatively, install ggstylekit from PRISM and then the tagged pmxhelpr release from GitHub with devtools:
# install.packages("devtools")
install.packages("ggstylekit",
repos = c("https://prism.dev.a2-ai.cloud/rpkgs/ggstylekit/0.4.0",
getOption("repos")))
devtools::install_github("ryancrass/pmxhelpr@v0.6.0")The README examples use a few packages from Suggests that aren’t installed automatically:
install.packages(c("dplyr", "ggplot2", "forcats", "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 -
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
-
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()— 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.
A finished plot can be restyled after the fact with restyle_plot(), additional variables in the dataset can be surfaced 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()returns avpc_statslist anddf_doseprop()returns adoseprop_statsdata.frame. Each carriesprint(),summary(), andas.data.frame()methods plus a predicate (is_vpc_stats(),is_doseprop_stats()). - Dual-mode plotting —
plot_vpc_cont()andplot_doseprop()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). The lower-level renderersplot_build_vpc()/plot_build_doseprop()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 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
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,
style = style_dvtime(alphas = c(obs_point = 0))) +
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)")
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 %>%
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)
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_wleg