One record per subject, analyte and timepoint, carrying nominal and actual time from first dose, actual time since the most recent dose, the dose in force, subject-level covariates, and an explicit, documented policy for values below the limit of quantification.

make_adpc(
  pc,
  adsl,
  ex = NULL,
  blq = c("half", "zero", "drop", "keep"),
  lloq = NULL,
  keep = NULL
)

Arguments

pc

Concentration data: one record per subject, analyte and timepoint. Must contain USUBJID, PARAMCD, the concentration column AVAL and the actual time column AFRLT. NFRLT, PARAM, AVISIT, AVALU and LLOQ are carried when present.

adsl

Subject-level dataset with USUBJID. Columns named in keep are merged onto every record.

ex

Optional dosing data with USUBJID, EXDOSE and a dose time in AFRLT (and NFRLT for the nominal dose time). When supplied, ARRLT, NRRLT and EXDOSE are derived from it. When NULL, time since dose is taken to be time since first dose, which is only correct for a single-dose profile — the function says so with a warning.

blq

BLQ policy: "half", "zero", "drop" or "keep".

lloq

Limit of quantification to use when pc has no LLOQ column. A single number, applied to every record.

keep

Character vector of adsl columns to carry onto the analysis dataset. NULL (default) carries every column of adsl except USUBJID and any name already present in pc.

Value

An eradam_adpc object: a tibble::tibble with one record per subject, analyte and timepoint.

Below the limit of quantification

A record is treated as BLQ when its concentration is missing (the usual way a <LLOQ result arrives once PCSTRESN has been left empty) or when it is strictly below the limit of quantification in force. BLQFL records that judgement on every record, whatever the policy, so the count is always recoverable from the delivered dataset.

The policy is an argument because no standard picks one for you. Regulatory guidance is silent and the pharmacometrics literature treats the choice as part of the analysis (Beal, "Ways to fit a PK model with some data below the quantification limit", J Pharmacokinet Pharmacodyn 2001, describes the M1–M7 family; dropping BLQ is M1, imputing is M5/M6).

  • "half" (default) — AVAL is set to LLOQ / 2 and DTYPE to "LOQ".

  • "zero"AVAL is set to 0 and DTYPE to "LOQ".

  • "drop" — the record is removed from the dataset entirely.

  • "keep"AVAL is left missing and ANL01FL is not set.

DTYPE = "LOQ" is the ADaM controlled-terminology value for a record whose analysis value was imputed from the limit of quantification, so an imputed record is always distinguishable from an observed one.

Conventions

Variable names follow the CDISC ADaM Implementation Guide for Non-compartmental Analysis Input Data (ADNCA v1.0): NFRLT, AFRLT, NRRLT, ARRLT for nominal and actual time from first and from most recent dose, with ARRLT negative on pre-dose records. DTYPE, AVAL, AVALC, AVALU, PARAMCD, PARAM and ANL01FL are standard ADaM BDS variables. BLQFL and LLOQ are not CDISC-standard names; this package uses them because a delivered PK dataset is unusable without them being somewhere.

This function replaces the SAS idiom of a PROC SORT + DATA step over PC/EX with a retained "last dose time" variable and an if PCSTRESC = '<LLOQ' then ... block.

Output structure

VariableMeaningSource
STUDYIDStudy identifierpc
USUBJIDUnique subject identifierpc
PARAMCDAnalyte codepc
PARAMAnalyte descriptionpc
AVISITAnalysis visitpc (kept when present)
NFRLTNominal time from first dose (h)pc
AFRLTActual time from first dose (h)pc
NRRLTNominal time from most recent dose (h)Derived from ex nominal dose times
ARRLTActual time from most recent dose (h); negative before the first doseDerived from ex actual dose times
AVALAnalysis concentration after the BLQ policy has been appliedpc / derived
AVALCCharacter analysis value; the reported result, or "<lloq" (e.g. "<0.5") for BLQ recordsDerived
AVALUConcentration unitpc (kept when present)
LLOQLower limit of quantification in force for the recordpc column LLOQ or argument lloq
BLQFL"Y" when the original result was below the limit of quantificationDerived
DTYPE"LOQ" when AVAL was imputed from the limit of quantification, otherwise NADerived (ADaM DTYPE codelist)
EXDOSEDose amount in effect at the sample timeex
ANL01FL"Y" when AVAL is non-missing and the record is usable for analysisDerived
<covariates>Subject-level variables carried from ADSLadsl (argument keep)

Examples

pc <- eradam_example("pc")
ex <- eradam_example("ex")
adsl <- eradam_example("adsl")

adpc <- make_adpc(pc, adsl, ex)
adpc
#> 
#> ── eradam ADPC ─────────────────────────────────────────────────────────────────
#>  576 record(s) | 24 subject(s) | 2 analyte(s)
#>  BLQ policy: half | 48 BLQ record(s) in output
#> # A tibble: 576 × 24
#>    STUDYID  USUBJID    PARAMCD PARAM AVISIT NFRLT AFRLT NRRLT ARRLT   AVAL AVALC
#>    <chr>    <chr>      <chr>   <chr> <chr>  <dbl> <dbl> <dbl> <dbl>  <dbl> <chr>
#>  1 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 1    0    0      0    0      0.25 <0.5 
#>  2 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 1    0.5  0.58   0.5  0.58 230.   229.…
#>  3 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 1    1    1.01   1    1.01 348.   347.…
#>  4 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 1    2    2.03   2    2.03 378.   378.…
#>  5 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 1    4    4.03   4    4.03 355.   355.…
#>  6 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 1    8    7.99   8    7.99 139.   139.…
#>  7 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 1   12   12.0   12   12.0   83.1  83.0…
#>  8 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 2   24   23.9    0   23.9   14.8  14.7…
#>  9 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 2   25   25.0    1    1.03 343.   343.…
#> 10 ERADAM01 ERADAM01-… DRUGX   DRUG… Day 2   28   28.0    4    3.98 298.   297.…
#> # ℹ 566 more rows
#> # ℹ 13 more variables: AVALU <chr>, LLOQ <dbl>, BLQFL <chr>, DTYPE <chr>,
#> #   EXDOSE <dbl>, ANL01FL <chr>, ARM <chr>, TRT01P <chr>, AGE <int>, SEX <chr>,
#> #   RACE <chr>, WTBL <dbl>, CRCL <dbl>

# the BLQ policy is an argument, never a hardcoded rule
table(make_adpc(pc, adsl, ex, blq = "zero")$AVAL == 0)
#> 
#> FALSE  TRUE 
#>   528    48 
nrow(make_adpc(pc, adsl, ex, blq = "drop"))
#> [1] 528