pharmacokinetics
Pharmacokinetic and pharmacodynamic analysis in R, including NCA, compartmental modeling, and bioequivalence.
What this skill does
# Pharmacokinetics and Pharmacodynamics in R
## Overview
Comprehensive pharmacokinetic (PK) and pharmacodynamic (PD) modeling in R covering non-compartmental analysis (NCA), compartmental PK modeling, population PK with nonlinear mixed effects, bioequivalence assessment, PK/PD modeling, and drug-drug interaction evaluation.
## Non-Compartmental Analysis (NCA)
### Using PKNCA Package
```r
library(PKNCA)
# Prepare concentration data
conc_data <- data.frame(
subject = rep(1:3, each = 8),
time = rep(c(0, 0.5, 1, 2, 4, 8, 12, 24), 3),
concentration = c(
0, 450, 380, 290, 180, 85, 40, 12,
0, 520, 410, 320, 200, 95, 45, 15,
0, 480, 395, 305, 190, 90, 42, 13
)
)
# Prepare dose data
dose_data <- data.frame(
subject = 1:3,
time = 0,
dose = 100 # mg
)
# Create PKNCA objects
conc_obj <- PKNCAconc(concentration ~ time | subject, data = conc_data)
dose_obj <- PKNCAdose(dose ~ time | subject, data = dose_data)
# Combine into analysis object
data_obj <- PKNCAdata(conc_obj, dose_obj)
# Run NCA
results <- pk.nca(data_obj)
# View results
summary(results)
as.data.frame(results)
```
### Custom NCA Parameters
```r
library(PKNCA)
# Specify intervals and parameters
intervals <- data.frame(
start = 0,
end = 24,
cmax = TRUE,
tmax = TRUE,
auclast = TRUE,
aucinf.obs = TRUE,
half.life = TRUE,
cl.obs = TRUE,
vss.obs = TRUE,
mrt.last = TRUE
)
# Create analysis with custom intervals
data_obj <- PKNCAdata(
conc_obj,
dose_obj,
intervals = intervals
)
results <- pk.nca(data_obj)
# Extract specific parameters
pk_summary <- summary(results)
# Individual subject parameters
individual_params <- as.data.frame(results) |>
tidyr::pivot_wider(
id_cols = subject,
names_from = PPTESTCD,
values_from = PPORRES
)
```
### Manual NCA Calculations
```r
# Basic NCA calculations for a single subject
calculate_nca <- function(time, conc, dose) {
# Cmax and Tmax
cmax <- max(conc)
tmax <- time[which.max(conc)]
# AUC by linear trapezoidal rule
auc_last <- sum(diff(time) * (head(conc, -1) + tail(conc, -1)) / 2)
# Terminal phase (last 3 points for lambda_z)
n_terminal <- 3
terminal_idx <- (length(time) - n_terminal + 1):length(time)
terminal_time <- time[terminal_idx]
terminal_conc <- conc[terminal_idx]
# Lambda_z from log-linear regression
fit <- lm(log(terminal_conc) ~ terminal_time)
lambda_z <- -coef(fit)[2]
# Half-life
half_life <- log(2) / lambda_z
# AUC extrapolated to infinity
auc_extrap <- tail(conc, 1) / lambda_z
auc_inf <- auc_last + auc_extrap
# Clearance (CL/F for oral)
cl_f <- dose / auc_inf
# Volume of distribution (Vd/F)
vd_f <- cl_f / lambda_z
# Mean residence time
# AUMC (first moment)
aumc <- sum(diff(time) * (head(time * conc, -1) + tail(time * conc, -1)) / 2)
aumc_extrap <- tail(conc, 1) / lambda_z^2 + tail(time * conc, 1) / lambda_z
aumc_inf <- aumc + aumc_extrap
mrt <- aumc_inf / auc_inf
return(data.frame(
Cmax = cmax,
Tmax = tmax,
AUClast = auc_last,
AUCinf = auc_inf,
Lambda_z = lambda_z,
Half_life = half_life,
CL_F = cl_f,
Vd_F = vd_f,
MRT = mrt
))
}
```
## Concentration-Time Visualization
### Spaghetti Plots
```r
library(ggplot2)
# Individual profiles (spaghetti plot)
ggplot(conc_data, aes(x = time, y = concentration, group = subject)) +
geom_line(alpha = 0.5) +
geom_point(alpha = 0.5) +
stat_summary(aes(group = 1), fun = mean, geom = "line",
color = "red", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point",
color = "red", size = 2) +
labs(x = "Time (hours)", y = "Concentration (ng/mL)",
title = "Concentration-Time Profile") +
theme_bw()
# Semi-log plot
ggplot(conc_data, aes(x = time, y = concentration, group = subject)) +
geom_line(alpha = 0.5) +
geom_point(alpha = 0.5) +
scale_y_log10() +
labs(x = "Time (hours)", y = "Concentration (ng/mL) - Log Scale",
title = "Semi-Logarithmic Concentration-Time Profile") +
theme_bw()
```
### Summary Plots with Error Bars
```r
library(ggplot2)
library(dplyr)
# Calculate summary statistics
conc_summary <- conc_data |>
group_by(time) |>
summarise(
mean_conc = mean(concentration),
sd_conc = sd(concentration),
geom_mean = exp(mean(log(concentration + 0.001))),
n = n(),
se_conc = sd_conc / sqrt(n)
)
# Mean + SD plot
ggplot(conc_summary, aes(x = time, y = mean_conc)) +
geom_line(size = 1) +
geom_point(size = 2) +
geom_errorbar(aes(ymin = mean_conc - sd_conc,
ymax = mean_conc + sd_conc),
width = 0.5) +
labs(x = "Time (hours)",
y = "Concentration (ng/mL)",
title = "Mean (± SD) Concentration-Time Profile") +
theme_bw()
# Geometric mean plot
ggplot(conc_summary, aes(x = time, y = geom_mean)) +
geom_line(size = 1) +
geom_point(size = 2) +
scale_y_log10() +
labs(x = "Time (hours)",
y = "Geometric Mean Concentration (ng/mL)",
title = "Geometric Mean Concentration Profile") +
theme_bw()
```
## Compartmental PK with mrgsolve
### One-Compartment Model
```r
library(mrgsolve)
# Define one-compartment model with first-order absorption
code_1cmt <- '
$PARAM CL = 10, V = 100, KA = 1.5
$CMT GUT CENT
$ODE
dxdt_GUT = -KA * GUT;
dxdt_CENT = KA * GUT - (CL/V) * CENT;
$TABLE
double CP = CENT / V;
$CAPTURE CP
'
# Compile model
mod_1cmt <- mcode("pk1cmt", code_1cmt)
# Single dose simulation
out <- mod_1cmt |>
ev(amt = 100, cmt = 1) |> # 100 mg oral dose
mrgsim(end = 24, delta = 0.1)
# Plot
plot(out, CP ~ time)
```
### Two-Compartment Model
```r
library(mrgsolve)
# Two-compartment model with central and peripheral
code_2cmt <- '
$PARAM CL = 10, V1 = 50, V2 = 100, Q = 15, KA = 1.2
$CMT GUT CENT PERIPH
$ODE
double K10 = CL / V1;
double K12 = Q / V1;
double K21 = Q / V2;
dxdt_GUT = -KA * GUT;
dxdt_CENT = KA * GUT - K10 * CENT - K12 * CENT + K21 * PERIPH;
dxdt_PERIPH = K12 * CENT - K21 * PERIPH;
$TABLE
double CP = CENT / V1;
$CAPTURE CP
'
mod_2cmt <- mcode("pk2cmt", code_2cmt)
# Simulate IV bolus
out_iv <- mod_2cmt |>
ev(amt = 100, cmt = 2) |> # IV bolus to central
mrgsim(end = 48, delta = 0.1)
plot(out_iv, CP ~ time, log = TRUE)
```
### Multiple Dosing
```r
library(mrgsolve)
# Multiple dose regimen
dosing_regimen <- ev(
amt = 100,
ii = 12, # Dosing interval (hours)
addl = 6, # Additional doses
cmt = 1 # Oral
)
out_multi <- mod_1cmt |>
ev(dosing_regimen) |>
mrgsim(end = 96, delta = 0.1)
plot(out_multi, CP ~ time)
# Steady-state check
out_ss <- mod_1cmt |>
ev(amt = 100, ii = 12, addl = 100, cmt = 1, ss = 1) |>
mrgsim(end = 24, delta = 0.1)
```
## Population PK with nlmixr2
### One-Compartment PopPK Model
```r
library(nlmixr2)
# Define population PK model
one_cmt_pop <- function() {
ini({
# Fixed effects (thetas)
tka <- log(1) # Log Ka
tcl <- log(10) # Log CL
tv <- log(100) # Log V
# Random effects (omegas)
eta.ka ~ 0.6 # IIV on Ka
eta.cl ~ 0.3 # IIV on CL
eta.v ~ 0.1 # IIV on V
# Residual error
add.err <- 0.1 # Additive
prop.err <- 0.1 # Proportional
})
model({
# Individual parameters
ka <- exp(tka + eta.ka)
cl <- exp(tcl + eta.cl)
v <- exp(tv + eta.v)
# Differential equations
d/dt(depot) <- -ka * depot
d/dt(central) <- ka * depot - cl/v * central
# Concentration
cp <- central / v
# Combined error model
cp ~ add(add.err) + prop(prop.err)
})
}
# Prepare data (nlmixr2 format)
pk_data <- data.frame(
ID = rep(1:10, each = 8),
TIME = rep(c(0, 0.5, 1, 2, 4, 8, 12, 24), 10),
DV = rnorm(80, 100, 20), # Observed concentrations
AMT = c(rep(c(100, rep(0, 7)), 10)),
EVID = c(rep(c(1, rep(0, 7)), 10)),
CMT = 1
)
# Fit model using SAEM
fit <- nlmixr2(one_cmt_pop, pk_data, est = "saem",
control = saemControl(print = 50))
# Summary
summary(fit)
# ParametRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.