Construct and validate dosing records for NCA using PKNCAdose(), and align dose data correctly with concentration profiles.
Tip
Big idea: NCA exposure metrics depend on both concentration data and correctly structured dose data. If dose records are misaligned, parameters like CL/F will be wrong.
Learning Objectives
By the end of this lesson, you will be able to:
Identify the minimum required columns for dosing data in NCA.
Construct a PKNCAdose() object using a formula interface.
Align dose records with concentration profiles (matching grouping).
Perform QC checks to validate dose–concentration consistency.
Interpret the unit implications of dose recorded as mg/kg.
Key Ideas
Dose data must align with the same grouping structure as concentration data.
Dose timing defines the reference for time-zero.
Derived parameters like \(CL/F\) depend directly on accurate dose records.
PKNCAdose() defines dose structure — it does not compute NCA.
Units propagate: if dose is in mg/kg, clearance will be in \(\mathrm{L/h/kg}\).
Using Theoph Dose Information
The built-in dataset Theoph includes a column Dose recorded in mg/kg.
Each subject received a single oral dose at time 0.
We will build a clean dosing table with standardized column names.
Dose unit note (important): In Theoph, DOSE is in mg/kg, not mg.
That’s totally fine for teaching NCA, but it affects any parameter that uses dose (especially clearance).
For example, since \(CL/F = \text{Dose} / AUC_{\infty}\):
dose_obj <-PKNCAdose(DOSE ~ TIME | ID, data = theoph_dose)dose_obj
Formula for dosing:
DOSE ~ TIME | ID
Nominal time column is not specified.
First 6 rows of dosing data:
ID TIME DOSE exclude route duration
1 0 4.02 <NA> extravascular 0
2 0 4.40 <NA> extravascular 0
3 0 4.53 <NA> extravascular 0
4 0 4.40 <NA> extravascular 0
5 0 5.86 <NA> extravascular 0
6 0 4.00 <NA> extravascular 0
Interpretation:
“DOSE is administered at TIME, and dose profiles are grouped by ID.”
No exposure metrics are calculated yet — this is a definition step.
Aligning Dose and Concentration Objects
Grouping must be consistent.
If concentration is defined as:
PKNCAconc(CONC ~ TIME | ID, data = conc_df)
Then dose must be defined as:
PKNCAdose(DOSE ~ TIME | ID, data = dose_df)
If you later include PERIOD or OCC for concentration, you must include it for dose too:
PKNCAconc(CONC ~ TIME | ID + PERIOD, data = conc_df)PKNCAdose(DOSE ~ TIME | ID + PERIOD, data = dose_df)
Worked Example: Misaligned Grouping (Common Real-World Mistake)
Many studies include multiple occasions (crossover periods, repeat dosing days).
If you define concentration profiles by ID + PERIOD but define dose only by ID, you are mixing profiles.
Below is a synthetic two-period example to demonstrate the pattern.
conc_with_two_periods <-as_tibble(Theoph) %>%transmute(ID = Subject, TIME = Time, CONC = conc) %>%mutate(PERIOD =1) %>%bind_rows(as_tibble(Theoph) %>%transmute(ID = Subject, TIME = Time, CONC = conc) %>%mutate(PERIOD =2) )dose_with_two_periods <- theoph_dose %>%mutate(PERIOD =1) %>%bind_rows(theoph_dose %>%mutate(PERIOD =2))
If we incorrectly define dose grouping as only ID, we lose the period structure:
bad_dose_attempt <-tryCatch(PKNCAdose(DOSE ~ TIME | ID, data = dose_with_two_periods),error =function(e) e)bad_dose_attempt
<simpleError in duplicate_check(object = ret, data_type = "dosing"): Rows that are not unique per group and time (column names: TIME, ID) found within dosing data. Row numbers: 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24>
Correct grouping keeps periods distinct:
good_dose_attempt <-PKNCAdose(DOSE ~ TIME | ID + PERIOD, data = dose_with_two_periods)good_dose_attempt
Formula for dosing:
DOSE ~ TIME | ID + PERIOD
Nominal time column is not specified.
First 6 rows of dosing data:
ID TIME DOSE PERIOD exclude route duration
1 0 4.02 1 <NA> extravascular 0
2 0 4.40 1 <NA> extravascular 0
3 0 4.53 1 <NA> extravascular 0
4 0 4.40 1 <NA> extravascular 0
5 0 5.86 1 <NA> extravascular 0
6 0 4.00 1 <NA> extravascular 0
Strategies
Build the dose dataset separately from the concentration dataset.
Make “one profile” explicit (ID + occasion/analyte/matrix as needed).
Match grouping variables exactly between PKNCAconc() and PKNCAdose().
Validate structure before running NCA.
Label units explicitly in outputs (especially when dose is mg/kg).
Common Mistakes
Warning
Forgetting to include PERIOD (or OCC) in dose grouping.
Using an incorrect dose time (not zero when TIME is post-dose).
Mixing mg and mg/kg without documenting it.
Treating “code ran” as “dose structure is correct.”
Practice Problems
Conceptual
Why must dose grouping match concentration grouping?
If dose is recorded too high, what happens to \(CL/F\)? Why?
Executable
Verify that theoph_dose has exactly one dose row per ID.
Create duplicated dose rows and detect the issue using count().
TipStep-by-Step Solutions
1. Grouping alignment:
Exposure metrics are computed per profile. If dose grouping differs from concentration grouping, dose and concentration won’t align, and derived parameters become incorrect.
2. Incorrect dose and \(CL/F\):
Since \(CL/F = \text{Dose}/AUC_{\infty}\), an inflated dose inflates \(CL/F\) directly (linearly).
3. One dose per ID:
theoph_dose %>%count(ID, name ="n_dose_rows") %>%filter(n_dose_rows >1)
# A tibble: 0 × 2
# ℹ 2 variables: ID <ord>, n_dose_rows <int>
4. Detect duplicated dose rows:
dup_dose <-bind_rows(theoph_dose, theoph_dose)dup_dose %>%count(ID, name ="n_dose_rows") %>%filter(n_dose_rows >1)