Skip to contents

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:

Installation

You can install the most recent tagged version of pmxhelpr from GitHub with:

# install.packages("devtools")
devtools::install_github("ryancrass/pmxhelpr@v0.5.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 a ggplot object
  • df_* — returns a data.frame
  • var_* — returns a vector (vectorized helpers for use inside mutate)
  • pmx_* — returns a theme element constructor (for use with *_theme factories)

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):

Theme System

Plot aesthetics are controlled through theme factories and element constructors. Each plot function has a corresponding plot_*_theme() factory:

Element constructors (pmx_*) create typed objects that map to ggplot2 geom aesthetics:

  • pmx_point() — point aesthetics (shape, size, alpha, color)
  • pmx_line() — line aesthetics (linewidth, linetype, alpha, color)
  • pmx_ribbon() — ribbon aesthetics (fill, alpha, color, linetype, linewidth)
  • pmx_errorbar() — error bar aesthetics (linewidth, linetype, alpha, width)
  • pmx_trend() — trend line aesthetics (linewidth, linetype, color, se_color, se_alpha)
  • pmx_color() — GOF overlay color mapping (dv, pred, ipred)
  • pmx_style() — convenience shortcut to set shared aesthetics (color, alpha) on both point and line elements of a role

S3 Class System

pmxhelpr returns class-tagged objects for both stats outputs and theme building blocks, with predicates and print()/summary() methods for interactive inspection and programmatic validation.

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 Themes and Aesthetics and VPC / Dose-Proportionality workflow articles for worked examples.

Vectorized Helpers

mrgsolve Wrappers

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_pkfitdata_sad with 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,
            theme = plot_dvtime_theme(obs_point = pmx_point(alpha = 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