---
title: "Extravascular (Oral/SC) Examples"
---
```{r setup, include=FALSE}
library(PKNCA)
library(dplyr)
library(ggplot2)
conflicted::conflicts_prefer(dplyr::filter, dplyr::select, .quiet = TRUE)
```
## The EV dataset: Theophylline
We use `datasets::Theoph` — oral theophylline (bronchodilator) in 12 subjects, sampled over 25 hours after a single oral dose. The package authors' worked analysis of this dataset is in the vignette [Computing NCA Parameters for Theophylline](https://humanpred.github.io/pknca/articles/v02-example-theophylline.html).
```{r}
head(Theoph)
str(Theoph)
```
Columns: `Subject`, `Wt` (body weight, kg), `Dose` (mg/kg), `Time` (h), `conc` (mg/L).
```{r}
# Prepare concentration data
d_conc <- as.data.frame(Theoph) |>
rename(time = Time, subject = Subject)
# Prepare dose data: convert mg/kg to mg per subject
d_dose <- Theoph |>
as.data.frame() |>
group_by(Subject) |>
summarise(dose = Dose[1] * Wt[1], .groups = "drop") |>
rename(subject = Subject) |>
mutate(time = 0)
# Visualize concentration profiles
ggplot(d_conc, aes(x = time, y = conc, group = subject, colour = subject)) +
geom_line() + geom_point() +
labs(title = "Theophylline oral — concentration-time profiles",
x = "Time (h)", y = "Concentration (mg/L)") +
theme_minimal()
```
The typical absorption-distribution-elimination shape is visible: concentrations rise to a peak (Tmax/Cmax) then decline.
---
## Basic extravascular analysis
```{r}
o_conc <- PKNCAconc(d_conc, conc ~ time | subject)
o_dose <- PKNCAdose(d_dose, dose ~ time | subject, route = "extravascular")
# Core EV parameters
ev_intervals <- data.frame(
start = 0,
end = Inf,
cmax = TRUE,
tmax = TRUE,
auclast = TRUE,
aucinf.obs = TRUE,
half.life = TRUE,
lambda.z = TRUE,
cl.obs = TRUE, # apparent CL (= CL/F for EV)
vz.obs = TRUE # apparent Vz (= Vz/F for EV)
)
o_data <- PKNCAdata(o_conc, o_dose, intervals = ev_intervals)
o_nca <- pk.nca(o_data)
as.data.frame(o_nca) |>
select(subject, PPTESTCD, PPORRES) |>
arrange(subject, PPTESTCD)
```
---
## Parameter reference
### Concentration and time landmarks
| Parameter | Meaning |
|---|---|
| `cmax` | Maximum observed concentration |
| `tmax` | Time of Cmax |
| `cmin` | Minimum observed concentration in the interval |
| `tmin` | Time of the minimum observed concentration (≥ 0.12.2) |
| `tfirst` | First time with a non-zero (non-BLQ) concentration |
| `tlast` | Last time with a measurable concentration |
| `clast.obs` | Observed concentration at `tlast` |
| `clast.pred` | Predicted concentration at `tlast` (from λz fit) |
| `count_conc` | Total observations (including BLQ) |
| `count_conc_measured` | Observations above LOQ (non-BLQ) |
| `lambda.z.time.last` | Last timepoint used in the λz regression |
```{r}
lm_interval <- data.frame(
start = 0,
end = Inf,
cmax = TRUE,
tmax = TRUE,
cmin = TRUE,
tmin = TRUE,
tfirst = TRUE,
tlast = TRUE,
clast.obs = TRUE,
clast.pred = TRUE,
count_conc = TRUE,
count_conc_measured = TRUE
)
o_nca_lm <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = lm_interval))
as.data.frame(o_nca_lm) |>
filter(PPTESTCD %in% c("cmax","tmax","cmin","tmin","tfirst","tlast",
"clast.obs","clast.pred","count_conc","count_conc_measured")) |>
select(subject, PPTESTCD, PPORRES) |>
arrange(subject, PPTESTCD)
```
**When the maximum occurs at more than one timepoint** (an exact tie), the default is to return the first Tmax. Control this with `first.tmax`:
```{r}
# Use the last Tmax when there are ties
o_data_lasttmax <- PKNCAdata(
o_conc, o_dose,
intervals = ev_intervals,
options = list(first.tmax = FALSE)
)
o_nca_lasttmax <- pk.nca(o_data_lasttmax)
# Tmax is unchanged for every subject:
identical(
as.data.frame(o_nca) |> filter(PPTESTCD == "tmax") |> pull(PPORRES),
as.data.frame(o_nca_lasttmax) |> filter(PPTESTCD == "tmax") |> pull(PPORRES)
)
```
The option has no effect here because no Theoph subject reaches its maximum concentration at two timepoints — `first.tmax` only matters when the maximum is an exact tie. Tie-breaking for Tmin is controlled by the `first.tmin` option (≥ 0.12.2; default `TRUE` = return first occurrence). All calculation options are cataloged in [Options for Controlling PKNCA](https://humanpred.github.io/pknca/articles/v40-options-for-controlling-PKNCA.html).
### AUC variants
The AUC family covers exposure to the last measurable concentration (`auclast`) and exposure extrapolated to infinity using either the observed or the λz-predicted Clast (`aucinf.obs` / `aucinf.pred`), with `aucpext.obs` reporting how much of AUCinf was extrapolated. See the [AUC chapter](auc-methods.qmd) for the full AUC family and the integration methods behind it.
| Parameter | Meaning |
|---|---|
| `auclast` | AUC from 0 to last measurable concentration |
| `aucinf.obs` | AUC extrapolated to ∞ (using observed Clast) |
| `aucinf.pred` | AUC extrapolated to ∞ (using predicted Clast) |
| `aucpext.obs` | % of AUCinf that is extrapolated |
```{r}
auc_params <- data.frame(
start = 0,
end = Inf,
auclast = TRUE,
aucinf.obs = TRUE,
aucinf.pred = TRUE,
aucpext.obs = TRUE
)
o_data_auc <- PKNCAdata(o_conc, o_dose, intervals = auc_params)
o_nca_auc <- pk.nca(o_data_auc)
as.data.frame(o_nca_auc) |>
filter(PPTESTCD %in% c("auclast", "aucinf.obs", "aucinf.pred", "aucpext.obs")) |>
select(subject, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES) |>
arrange(subject)
```
### Half-life and λz
For EV, the terminal phase reflects elimination (not absorption) once absorption is complete. One extravascular-specific caveat: with slow absorption the terminal slope can reflect absorption rather than elimination (flip-flop kinetics), in which case the apparent half-life is an absorption half-life. The usual λz quality controls — enough points in the regression, adjusted R², and span ratio — apply regardless of route; see the [Half-Life chapter](halflife.qmd) for point selection and quality thresholds. The λz point-selection algorithm and quality metrics are detailed in the [Half-Life Calculation vignette](https://humanpred.github.io/pknca/articles/v06-half-life-calculation.html).
```{r}
hl_params <- data.frame(
start = 0,
end = Inf,
lambda.z = TRUE,
half.life = TRUE,
lambda.z.n.points = TRUE,
r.squared = TRUE,
adj.r.squared = TRUE
)
o_data_hl <- PKNCAdata(o_conc, o_dose, intervals = hl_params)
o_nca_hl <- pk.nca(o_data_hl)
as.data.frame(o_nca_hl) |>
filter(PPTESTCD %in% c("half.life", "lambda.z.n.points", "adj.r.squared")) |>
select(subject, PPTESTCD, PPORRES) |>
arrange(subject, PPTESTCD)
```
**Allow or exclude Tmax from the terminal regression:**
By default, the Tmax point is excluded from the λz regression (absorption may still be ongoing). You can override this:
```{r}
o_data_allow_tmax <- PKNCAdata(
o_conc, o_dose,
intervals = hl_params,
options = list(allow.tmax.in.half.life = TRUE)
)
o_nca_allow_tmax <- pk.nca(o_data_allow_tmax)
# Subject 8 is the only subject whose selected regression changes
bind_rows(
as.data.frame(o_nca_hl) |> mutate(version = "default (Tmax excluded)"),
as.data.frame(o_nca_allow_tmax) |> mutate(version = "Tmax allowed")
) |>
filter(subject == "8",
PPTESTCD %in% c("lambda.z.n.points", "adj.r.squared", "half.life")) |>
select(version, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES)
```
For the other 11 subjects the best-fitting regression already excluded Tmax, so nothing changes; subject 8's best fit (highest adjusted R²) now starts at Tmax, using one more point and shifting the half-life slightly.
### Clearance and volume (apparent)
For extravascular dosing the fraction absorbed (F) is unknown, so clearance and volume cannot be separated from it: PKNCA's `cl.*` and `vz.*` values are apparent, i.e. CL/F and Vz/F. The formulas are the same as for IV dosing (Dose / AUC, then CL / λz), with F implicitly in the denominator — both are requested in the basic analysis above.
| Parameter | Meaning |
|---|---|
| `cl.obs` | Apparent clearance = Dose / AUCinf.obs (this is CL/F) |
| `vz.obs` | Apparent volume = CL.obs / λz (this is Vz/F) |
### Lag time (tlag)
`tlag` is the time before absorption begins — the delay between dosing and the first measurable rise in concentration. Common for enteric-coated formulations or SC injections with a diffusion delay.
```{r}
o_nca_tlag <- pk.nca(PKNCAdata(o_conc, o_dose,
intervals = data.frame(start = 0, end = Inf, tlag = TRUE, tmax = TRUE, cmax = TRUE)))
as.data.frame(o_nca_tlag) |>
filter(PPTESTCD %in% c("tlag", "tmax", "cmax")) |>
select(subject, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES) |>
arrange(subject)
```
> For the Theoph dataset, tlag is 0 for all subjects (no lag). It becomes non-zero when the concentration-time profile shows a flat period after dosing before rising.
### Bioavailability (f)
`f` (relative bioavailability via `pk.calc.f()`) requires paired test/reference treatments in the grouping structure — see the [Bioavailability](#bioavailability) section below.
### Volume at steady state (Vss)
Vss is computed from CL and MRT, so for extravascular dosing `vss.obs` and `vss.pred` are the apparent Vss (i.e., Vss/F). `vss.last` uses MRTlast instead of the extrapolated MRT.
```{r}
vss_params <- data.frame(
start = 0,
end = Inf,
vss.obs = TRUE, # apparent Vss = CL.obs × MRT.obs
vss.pred = TRUE,
vss.last = TRUE # uses MRTlast
)
o_nca_vss <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = vss_params))
as.data.frame(o_nca_vss) |>
filter(grepl("^vss", PPTESTCD)) |>
select(subject, PPTESTCD, PPORRES) |>
arrange(subject, PPTESTCD)
```
### Mean residence time (MRT)
| Parameter | Meaning |
|---|---|
| `mrt.last` | AUMC(0–last) / AUC(0–last) |
| `mrt.obs` | AUMC(0–∞) / AUC(0–∞), observed Clast |
| `mrt.pred` | AUMC(0–∞) / AUC(0–∞), predicted Clast |
```{r}
mrt_ev_params <- data.frame(
start = 0, end = Inf,
mrt.last = TRUE,
mrt.obs = TRUE,
mrt.pred = TRUE
)
o_nca_mrt_ev <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = mrt_ev_params))
as.data.frame(o_nca_mrt_ev) |>
filter(grepl("^mrt", PPTESTCD)) |>
select(subject, PPTESTCD, PPORRES) |>
arrange(subject, PPTESTCD)
```
### Effective half-life and elimination rate constant
The effective half-life is ln(2) × MRT — a rate that reflects overall persistence rather than the terminal slope. The related `kel.*` parameters are 1/MRT, **not** λz; the two differ whenever distribution or absorption contributes materially to MRT.
All extravascular effective half-life and elimination rate constant variants:
| Parameter | Based on |
|---|---|
| `thalf.eff.last` | `mrt.last` |
| `thalf.eff.obs` | `mrt.obs` |
| `thalf.eff.pred` | `mrt.pred` |
| `kel.obs` | 1 / `mrt.obs` |
| `kel.pred` | 1 / `mrt.pred` |
| `kel.last` | 1 / `mrt.last` |
```{r}
eff_params <- data.frame(
start = 0, end = Inf,
thalf.eff.last = TRUE,
thalf.eff.obs = TRUE,
thalf.eff.pred = TRUE,
kel.obs = TRUE,
kel.pred = TRUE,
kel.last = TRUE
)
o_nca_eff <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = eff_params))
as.data.frame(o_nca_eff) |>
filter(grepl("^(thalf|kel)", PPTESTCD)) |>
select(subject, PPTESTCD, PPORRES) |>
arrange(subject, PPTESTCD)
```
---
## AUC over a specific interval
For multiple-dose studies, request AUC over the dosing interval (tau):
```{r}
# Single dose, but demonstrating syntax for AUC(0-tau)
tau_interval <- data.frame(
start = 0,
end = 24, # tau = 24 h
auclast = TRUE,
cmax = TRUE,
tmax = TRUE
)
o_data_tau <- PKNCAdata(o_conc, o_dose, intervals = tau_interval)
o_nca_tau <- pk.nca(o_data_tau)
as.data.frame(o_nca_tau) |> select(subject, PPTESTCD, PPORRES)
```
---
## Imputation of missing predose concentrations
In some studies, the predose sample is missing or was not collected. PKNCA can impute a time-0 concentration before calculations. Full method descriptions and per-interval examples are in the [Concentration Imputation chapter](imputation.qmd) and the [Data Imputation vignette](https://humanpred.github.io/pknca/articles/v08-data-imputation.html).
Available built-in methods (comma-separate to chain them):
| Method | What it does |
|---|---|
| `start_predose` | Uses the last pre-interval concentration at the interval start (no sample is added if no pre-interval observation exists) |
| `start_conc0` | Sets the predose concentration to 0 unconditionally |
| `start_cmin` | Uses the minimum observed concentration as predose value |
```{r}
# Remove the time=0 observation from subject 1 to simulate missing predose
d_conc_missing <- d_conc |>
filter(!(subject == "1" & time == 0))
o_conc_miss <- PKNCAconc(d_conc_missing, conc ~ time | subject)
# With imputation: start_conc0 adds conc = 0 at the interval start
o_data_imputed <- PKNCAdata(
o_conc_miss, o_dose,
intervals = ev_intervals,
impute = "start_conc0"
)
o_nca_imputed <- pk.nca(o_data_imputed)
# Compare subject 1 AUClast: original data vs. missing predose imputed as 0
bind_rows(
as.data.frame(o_nca) |> filter(subject == "1", PPTESTCD == "auclast") |> mutate(version = "original"),
as.data.frame(o_nca_imputed) |> filter(subject == "1", PPTESTCD == "auclast") |> mutate(version = "imputed")
) |>
select(version, PPTESTCD, PPORRES) |>
as.data.frame() # base print shows full precision; the difference is small
```
**Per-interval imputation** — apply different methods to different calculation windows:
```{r}
# Intervals with an "impute" column specifying method per row
d_intervals_impute <- data.frame(
start = 0,
end = Inf,
auclast = TRUE,
impute = "start_conc0"
)
o_data_per_interval <- PKNCAdata(
o_conc_miss, o_dose,
intervals = d_intervals_impute,
impute = "impute" # tells PKNCA to look in the intervals column named "impute"
)
o_nca_per_interval <- pk.nca(o_data_per_interval)
# Subject 1's missing predose is imputed by the interval row — same result as above
bind_rows(
as.data.frame(o_nca_imputed) |> mutate(version = "global impute"),
as.data.frame(o_nca_per_interval) |> mutate(version = "per-interval impute")
) |>
filter(subject == "1", PPTESTCD == "auclast") |>
select(version, PPTESTCD, PPORRES)
```
With a single interval row the per-interval column reproduces the global setting; with several rows, each row's `impute` value applies only to its own calculation window.
---
## Bioavailability
Bioavailability (F) compares dose-normalized exposure from the EV route against an IV reference. In PKNCA, F is computed via the `f` interval parameter — backed by `pk.calc.f()` — which requires the test and reference treatments to be distinguished in the grouping structure (e.g. a treatment or period column), with the reference AUC available for the ratio. Theoph (oral theophylline) and Indometh (IV indomethacin) are different drugs from different studies, so no real F can be computed here; the code below only illustrates the AUC inputs and the arithmetic:
```{r}
# IV reference (using Indometh as stand-in — illustrative syntax only)
d_iv_conc <- as.data.frame(Indometh)
d_iv_dose <- data.frame(Subject = unique(d_iv_conc$Subject), dose = 25, time = 0)
o_iv_conc <- PKNCAconc(d_iv_conc, conc ~ time | Subject)
o_iv_dose <- PKNCAdose(d_iv_dose, dose ~ time | Subject, route = "intravascular")
o_iv_data <- PKNCAdata(
o_iv_conc, o_iv_dose,
intervals = data.frame(start = 0, end = Inf, aucinf.obs = TRUE),
impute = "start_conc0" # Indometh has no t = 0 sample
)
o_iv_nca <- pk.nca(o_iv_data)
iv_aucinf <- as.data.frame(o_iv_nca) |>
filter(PPTESTCD == "aucinf.obs") |>
summarise(mean_aucinf = mean(PPORRES)) |>
pull(mean_aucinf)
ev_aucinf <- as.data.frame(o_nca_auc) |>
filter(PPTESTCD == "aucinf.obs") |>
summarise(mean_aucinf = mean(PPORRES)) |>
pull(mean_aucinf)
# F = (AUC_ev / Dose_ev) / (AUC_iv / Dose_iv); here only the AUC ratio is shown
cat(sprintf("Mean IV AUCinf (Indometh): %.2f\n", iv_aucinf))
cat(sprintf("Mean EV AUCinf (Theoph): %.2f\n", ev_aucinf))
cat(sprintf("AUC ratio EV/IV: %.1f — illustrative only, different drugs\n",
ev_aucinf / iv_aucinf))
```
> In a real bioavailability study, subjects receive both the IV reference and the EV test treatment, and `pk.calc.f()` computes F as the dose-normalized AUC ratio of test to reference. `f` is typically used in crossover bioequivalence studies — see `?pk.calc.f` for the full setup.
---
## Multiple-dose / steady-state
For multiple-dose data, request steady-state parameters over a tau interval — see the [Multiple-Dose chapter](multiple-dose.qmd) for the full workflow. To simulate steady state from single-dose data, see [Superposition of Pharmacokinetic Data](https://humanpred.github.io/pknca/articles/v20-superposition.html); to estimate when steady state is reached, see [Noncompartmental evaluation of time to steady-state](https://humanpred.github.io/pknca/articles/v22-time-to-steady-state.html). Here the interval syntax is demonstrated on the single-dose Theoph data:
```{r}
ss_intervals <- data.frame(
start = 0,
end = 24,
cmax = TRUE,
cmin = TRUE,
tmax = TRUE,
auclast = TRUE
)
o_data_ss <- PKNCAdata(o_conc, o_dose, intervals = ss_intervals)
o_nca_ss <- pk.nca(o_data_ss)
as.data.frame(o_nca_ss) |>
select(subject, PPTESTCD, PPORRES) |>
arrange(subject, PPTESTCD)
```
---
## Excluding observations
Mark individual timepoints to exclude (e.g. vomiting within 2× median Tmax, suspected contamination):
```{r}
d_conc_excl <- d_conc |>
mutate(
exclude_reason = ifelse(subject == "5" & time == 2.02,
"vomiting within 2x median Tmax", NA_character_)
)
o_conc_excl <- PKNCAconc(d_conc_excl, conc ~ time | subject, exclude = "exclude_reason")
# The flagged row stays in the data with its reason
as.data.frame(o_conc_excl) |> filter(!is.na(exclude_reason))
```
The excluded point is dropped from every parameter calculation, while the flagged row remains in the data with its reason (shown above), preserving the audit trail.
---
## BLQ (below limit of quantification) handling
PKNCA's `conc.blq` option controls how BLQ values (typically entered as 0) are treated:
The default is `list(first = "keep", middle = "drop", last = "keep")`:
- `first` — BLQs before the first non-BLQ concentration (keep, often a predose zero)
- `middle` — BLQs sandwiched between non-BLQ values (dropped by default)
- `last` — BLQs after the last non-BLQ concentration (keep by default)
In Theoph the only BLQ values are the predose zeros, which the default rule keeps, so overriding `conc.blq` changes little on this dataset. To see the mechanism, simulate a mid-profile BLQ — subject 3's 3.62 h sample set to 0 — and compare the default against a global `"keep"`:
```{r}
d_conc_blq <- d_conc |>
mutate(conc = ifelse(subject == "3" & time == 3.62, 0, conc))
o_conc_blq <- PKNCAconc(d_conc_blq, conc ~ time | subject)
auclast_interval <- data.frame(start = 0, end = Inf, auclast = TRUE)
# Default: the middle BLQ is dropped and the AUC interpolates across the gap
o_nca_blq_default <- pk.nca(PKNCAdata(o_conc_blq, o_dose, intervals = auclast_interval))
# Global override: keep all BLQ values as 0
o_data_blq_keep <- PKNCAdata(
o_conc_blq, o_dose,
intervals = auclast_interval,
options = list(conc.blq = "keep")
)
o_nca_blq_keep <- pk.nca(o_data_blq_keep)
bind_rows(
as.data.frame(o_nca_blq_default) |> mutate(version = "default (drop middle BLQ)"),
as.data.frame(o_nca_blq_keep) |> mutate(version = "conc.blq = \"keep\"")
) |>
filter(subject == "3", PPTESTCD == "auclast") |>
select(version, PPTESTCD, PPORRES)
```
Keeping the mid-profile 0 pulls the concentration curve down to 0 at 3.62 h and cuts a wedge out of subject 3's AUC; the default treats an isolated BLQ between measurable concentrations as an assay artifact and interpolates across it.
Overrides can also be per-position (`first`/`middle`/`last`) or relative to Tmax (`before.tmax`/`after.tmax`), and the action can be `"keep"`, `"drop"`, or a numeric replacement value. The objects are built the same way; running them on this data gives the results described below:
```{r}
# Global: remove all BLQ values
o_data_blq_drop <- PKNCAdata(
o_conc, o_dose,
intervals = ev_intervals,
options = list(conc.blq = "drop")
)
# Per-phase (before/after Tmax):
o_data_blq <- PKNCAdata(
o_conc, o_dose,
intervals = ev_intervals,
options = list(
conc.blq = list(
before.tmax = "keep", # keep 0s before Tmax (ascending phase)
after.tmax = "drop" # drop BLQs after Tmax
)
)
)
```
On Theoph the per-phase rule reproduces the default results (the predose zeros sit before Tmax and are kept), while the global `"drop"` is a trap for intervals starting at the dose time: it removes the predose zeros too, so AUCs that start at 0 begin before the first remaining measurement and return `NA` with a warning.
To use BLQ observations in half-life estimation rather than dropping them, see [Half-life calculation with Tobit regression](https://humanpred.github.io/pknca/articles/v06-half-life-calculation-tobit.html) (≥ 0.12.2).
---
## AUC integration methods
The default integration method is **lin up/log down** (linear interpolation on the ascending phase, log-linear on the descending phase). The alternatives, `"linear"` and `"lin-log"`, are selected per-analysis with the `auc.method` option. See the [AUC chapter](auc-methods.qmd) for how each method computes the trapezoids and when to prefer which. Formal definitions of each rule are in the [AUC integration methods vignette](https://humanpred.github.io/pknca/articles/v23-auc-integration-methods.html).
```{r}
# Switch to the linear trapezoidal method
o_data_lin <- PKNCAdata(o_conc, o_dose, intervals = ev_intervals,
options = list(auc.method = "linear"))
as.data.frame(pk.nca(o_data_lin)) |>
filter(PPTESTCD == "auclast") |>
select(subject, PPTESTCD, PPORRES) |>
head(3)
```
---
## Units
Assign units to get automatic unit propagation through derived parameters. See the [Units chapter](units.qmd) for the full units system, including unit conversion and per-parameter overrides. See also [Unit Assignment and Conversion with PKNCA](https://humanpred.github.io/pknca/articles/v07-unit-conversion.html) for the full units workflow.
```{r}
units_table <- pknca_units_table(
concu = "mg/L",
timeu = "h",
doseu = "mg",
amountu = "mg"
)
o_conc_u <- PKNCAconc(d_conc, conc ~ time | subject, concu = "mg/L", timeu = "h")
o_dose_u <- PKNCAdose(d_dose, dose ~ time | subject, route = "extravascular",
doseu = "mg", timeu = "h")
o_data_u <- PKNCAdata(o_conc_u, o_dose_u, intervals = ev_intervals, units = units_table)
o_nca_u <- pk.nca(o_data_u)
as.data.frame(o_nca_u) |>
filter(PPTESTCD %in% c("auclast", "aucinf.obs", "cl.obs", "half.life")) |>
select(subject, PPTESTCD, PPORRES) |>
arrange(subject, PPTESTCD)
```
---
## Summary with custom statistics
`summary()` produces a study-report-style table of summary statistics per parameter, and `PKNCA.set.summary()` customizes the statistics reported for any parameter — see [Post-processing](postprocessing.qmd) for the full summary workflow. More summary and exclusion workflows are in the [Post-Processing vignette](https://humanpred.github.io/pknca/articles/v07-post-processing.html).
```{r}
PKNCA.set.summary(
"tmax",
description = "median [min, max]",
point = median,
spread = function(x) c(min(x), max(x)) # must return numeric; PKNCA formats the string
)
summary(o_nca)
```
---
## Full parameter list for extravascular
All extravascular-relevant parameters you can request in an interval:
```{r}
interval_cols <- get.interval.cols()
ev_relevant <- c(
# Concentration / time landmarks
"cmax", "tmax", "cmin", "tmin", "tfirst", "tlast", "tlag",
"clast.obs", "clast.pred", "count_conc", "count_conc_measured",
# AUC family
"auclast", "aucall", "aucinf.obs", "aucinf.pred",
"aucpext.obs", "aucpext.pred",
"aucint.last", "aucint.last.dose", "aucint.all", "aucint.all.dose",
"aucint.inf.obs", "aucint.inf.obs.dose",
# AUMC
"aumclast", "aumcall", "aumcinf.obs", "aumcinf.pred",
# Half-life / λz
"half.life", "lambda.z", "lambda.z.n.points", "lambda.z.time.first", "lambda.z.time.last",
"r.squared", "adj.r.squared", "span.ratio",
# Clearance (apparent)
"cl.obs", "cl.pred", "cl.last", "cl.all",
# Volume (apparent)
"vz.obs", "vz.pred", "vss.obs", "vss.pred", "vss.last",
# MRT
"mrt.last", "mrt.obs", "mrt.pred",
# Effective half-life / kel
"thalf.eff.last", "thalf.eff.obs", "thalf.eff.pred",
"kel.obs", "kel.pred", "kel.last",
# Bioavailability
"f",
# Dose-normalized
"auclast.dn", "aucinf.obs.dn", "cmax.dn", "clast.obs.dn"
)
sort(names(interval_cols)[names(interval_cols) %in% ev_relevant])
```
---
::: {.callout-note icon=false appearance="minimal"}
**pkgdown reference:** [PKNCAconc()](https://humanpred.github.io/pknca/reference/PKNCAconc.html) · [PKNCAdose()](https://humanpred.github.io/pknca/reference/PKNCAdose.html) · [PKNCAdata()](https://humanpred.github.io/pknca/reference/PKNCAdata.html) · [pk.nca()](https://humanpred.github.io/pknca/reference/pk.nca.html) · [pk.calc.f()](https://humanpred.github.io/pknca/reference/pk.calc.f.html) · [pknca_units_table()](https://humanpred.github.io/pknca/reference/pknca_units_table.html) · [PKNCA.set.summary()](https://humanpred.github.io/pknca/reference/PKNCA.set.summary.html) · [get.interval.cols()](https://humanpred.github.io/pknca/reference/get.interval.cols.html) · [summary()](https://humanpred.github.io/pknca/reference/summary.PKNCAresults.html) · [PKNCA_impute_method_start_*()](https://humanpred.github.io/pknca/reference/PKNCA_impute_method.html)
:::