| name | admiral-adrs |
| description | Derives an ADaM Tumor Response Analysis Dataset (ADRS) using the {admiral} and {admiralonco} R packages. Use when a user needs to create ADRS from SDTM RS domain data, derive RECIST 1.1 response parameters (overall response, confirmed response, best overall response, clinical benefit), or generate QC-ready R code following CDISC ADaM and oncology conventions. Requires SDTM RS input data, ADSL with randomization and treatment dates, and an ADaM ADRS specification.
|
| license | MIT |
| metadata | {"author":"Navitas Data Sciences","version":"0.1","pharmaverse":"true","parent":"admiral"} |
| compatibility | Requires R with admiral, admiralonco, dplyr, lubridate, and pharmaversesdtm installed. Requires a completed ADSL dataset with RANDDT and TRTSDT. Designed for use in a GxP-compliant oncology trial environment with access to SDTM RS domain data and an ADaM ADRS specification.
|
admiral-adrs
Shared conventions (library setup, pipe style, date rules, flag convention,
# REVIEW: annotations, stopifnot() patterns) are defined in the parent
../SKILL.md. The workflow below is ADRS-specific.
Derives a CDISC-conformant ADRS tumor response dataset using {admiral} and
{admiralonco}. Outputs executable, QC-ready R code covering RECIST 1.1 response
parameters with full derivation traceability.
The primary design challenge in ADRS is the confirmation logic: CR and PR
must be supported by a second qualifying assessment ≥28 days later. Best Overall
Response (BOR) follows a strict hierarchy (CR > PR > SD > NON-CR/NON-PD > PD >
NE) and handles NE propagation in ways that manual case_when() or slice_min()
cannot replicate correctly. Always use admiralonco functions — never manual
derivations.
Inputs
Before generating code, confirm the following are available or explicitly noted
as absent:
| Input | Required | Notes |
|---|
| RS | Yes | One record per tumor assessment per subject; RSSTRESC contains the response category (CR/PR/SD/PD/NE) |
| ADSL | Yes | Provides TRTSDT, RANDDT, treatment labels, population flags |
| ADaM ADRS spec | Yes | Parameter list, PARAMCD/PARAM mapping, confirmation window, clinical benefit definition |
| Study context | Yes | RECIST version (1.0 vs 1.1), assessor (investigator vs BICR), confirmation window, clinical benefit anchor date |
If RS or ADSL are absent, stop and request them.
Note on pharmaversesdtm test data: The pharmaversesdtm package no longer
exports a plain rs object. Use pharmaversesdtm::rs_onco_recist for test or
benchmark runs. When working with real study data, load RS from the study's
SDTM package or file path.
Workflow
Follow these steps in order. Generate code section by section, not as a single
block.
Step 1 — Setup and domain loading
library(admiral)
library(admiralonco)
library(dplyr)
library(lubridate)
library(pharmaversesdtm)
rs <- pharmaversesdtm::rs_onco_recist
adsl <- adsl
stopifnot(nrow(rs) > 0)
Step 2 — DOMAIN removal
Remove DOMAIN from RS before any derive_param_*() or derive_vars_merged()
calls. admiral errors when DOMAIN exists in both the dataset and a source dataset
passed to these functions.
rs <- rs |> select(-DOMAIN)
Step 3 — Merge ADSL backbone variables
Bring required ADSL variables into the RS dataset before parameter derivation.
At minimum: RANDDT and TRTSDT (clinical benefit anchor and study day reference),
treatment labels, and population flags.
adrs <- rs |>
derive_vars_merged(
dataset_add = adsl,
by_vars = exprs(STUDYID, USUBJID),
new_vars = exprs(RANDDT, TRTSDT, TRT01P, TRT01PN, TRT01A, TRT01AN,
ITTFL, SAFFL)
)
Step 4 — Date derivation (ADT, ADTF, ADY)
Derive the analysis date from RSDTC. This must happen before any
derive_param_*() call — admiralonco response functions use ADT internally for
confirmation window comparisons.
adrs <- adrs |>
derive_vars_dt(
dtc = RSDTC,
new_vars_prefix = "A",
date_imputation = "first",
flag_imputation = "auto"
) |>
derive_vars_dy(
reference_date = TRTSDT,
source_vars = exprs(ADT)
)
Step 5 — Analysis value (AVALC, AVAL)
Set AVALC from RSSTRESC and derive the numeric AVAL using the admiralonco helper
aval_resp(). This function maps response categories to a monotone numeric scale:
CR=1, PR=2, SD=3, NON-CR/NON-PD=4, PD=5, NE=6.
adrs <- adrs |>
mutate(
AVALC = RSSTRESC,
AVAL = aval_resp(AVALC)
)
Step 6 — Overall response parameter (OVRLRESP)
Add OVRLRESP records — one per subject per assessment timepoint. This parameter
carries the verbatim response at each visit; it is not confirmation-adjusted.
adrs <- adrs |>
derive_param_response(
dataset_adsl = adsl,
filter_source = RSEVAL == "INVESTIGATOR" & RSEVALID == "RECIST 1.1",
source_var = RSSTRESC,
set_values_to = exprs(
PARAMCD = "OVRLRESP",
PARAM = "Overall Response by Investigator"
)
)
Step 7 — Unconfirmed response flag (RSP)
Add RSP records — one per subject, indicating whether any CR or PR was observed
(unconfirmed). Retained alongside CONFIRMED to enable the ORR verification check
in Step 11.
adrs <- adrs |>
derive_param_response(
dataset_adsl = adsl,
filter_source = RSEVAL == "INVESTIGATOR" & RSEVALID == "RECIST 1.1",
source_var = RSSTRESC,
resp_val = c("CR", "PR"),
set_values_to = exprs(
PARAMCD = "RSP",
PARAM = "Response (Unconfirmed)"
)
)
Step 8 — Confirmed response (CONFIRMED)
A CR or PR is confirmed when a second qualifying assessment ≥ ref_confirm days
after the first also shows CR or PR. CONFIRMED = "Y" if the subject has at least
one confirmed CR or PR; "N" otherwise.
Flag convention note: CONFIRMED uses "Y"/"N", not "Y"/NA — this is
the documented admiralonco contract. See
Flag convention exception
below. Do not recode "N" to NA.
adrs <- adrs |>
derive_param_confirmed_resp(
dataset_adsl = adsl,
filter_source = RSEVAL == "INVESTIGATOR" & RSEVALID == "RECIST 1.1",
source_var = RSSTRESC,
ref_confirm = 28,
set_values_to = exprs(
PARAMCD = "CONFIRMED",
PARAM = "Confirmed Response"
)
)
Step 9 — Best overall response (BESTRESP)
BOR applies the RECIST 1.1 hierarchy across all assessments for each subject.
derive_param_confirmed_bor() handles confirmation requirements, the NE
propagation rule, and the hierarchy correctly. Never substitute slice_min(AVAL)
or manual case_when() — these cannot replicate the NE propagation logic.
adrs <- adrs |>
derive_param_confirmed_bor(
dataset_adsl = adsl,
filter_source = RSEVAL == "INVESTIGATOR" & RSEVALID == "RECIST 1.1",
source_var = RSSTRESC,
ref_confirm = 28,
missing_as_ne = FALSE,
set_values_to = exprs(
PARAMCD = "BESTRESP",
PARAM = "Best Overall Response (Confirmed)"
)
)
Step 10 — Clinical benefit (CBRESPFL)
Clinical benefit is a durable non-progressive response: CR, PR, or SD sustained
for ≥ ref_start_window days from reference_date. CBRESPFL = "Y" if criteria
are met; "N" otherwise.
Flag convention note: CBRESPFL uses "Y"/"N", not "Y"/NA. Same
admiralonco contract as CONFIRMED — do not recode.
adrs <- adrs |>
derive_param_clinbenefit(
dataset_adsl = adsl,
filter_source = RSEVAL == "INVESTIGATOR" & RSEVALID == "RECIST 1.1",
source_var = RSSTRESC,
reference_date = RANDDT,
ref_start_window = 42,
set_values_to = exprs(
PARAMCD = "CBRESPFL",
PARAM = "Clinical Benefit"
)
)
Step 11 — Verification: confirmed vs unconfirmed ORR
Print response counts side-by-side and assert that confirmed ORR cannot exceed
unconfirmed ORR. A confirmed count greater than unconfirmed count signals a
configuration error in the confirmation window.
response_summary <- adrs |>
filter(PARAMCD %in% c("RSP", "CONFIRMED", "CBRESPFL")) |>
count(PARAMCD, AVALC)
print(response_summary)
n_confirmed <- sum(adrs$PARAMCD == "CONFIRMED" & adrs$AVALC == "Y", na.rm = TRUE)
n_unconfirmed <- sum(adrs$PARAMCD == "RSP" & adrs$AVALC == "Y", na.rm = TRUE)
stopifnot(n_confirmed <= n_unconfirmed)
stopifnot(
adrsPARAMCD adrsAVALC
adrsAVAL aval_resp
na.rm
Step 12 — Final checks
required_params <- c("OVRLRESP", "RSP", "CONFIRMED", "BESTRESP", "CBRESPFL")
missing_params <- setdiff(required_params, unique(adrs$PARAMCD))
if (length(missing_params) > 0) {
stop("Missing required ADRS parameters: ", paste(missing_params, collapse = ", "))
}
dup_check <- adrs |>
filter(PARAMCD %in% c("BESTRESP", "CONFIRMED", "RSP", "CBRESPFL")
countSTUDYID USUBJID PARAMCD
filtern
nrowdup_check
stop
pastepastedup_checkUSUBJID dup_checkPARAMCD collapse
required_vars
missing_vars setdiffrequired_vars adrs
missing_vars
stop pastemissing_vars collapse
Flag convention exception for CONFIRMED and CBRESPFL
The admiral family convention is "Y" or NA — never "N" — for flag variables.
ADRS has two named exceptions:
| Variable | Values | Reason |
|---|
CONFIRMED | "Y" / "N" | admiralonco contract: "N" means assessed but unconfirmed, not missing |
CBRESPFL | "Y" / "N" | admiralonco contract: same logic as CONFIRMED |
Do not recode "N" to NA for these variables. The "N" records are
required by downstream derive_param_confirmed_bor() logic to correctly
identify subjects with no confirmed response. Recoding them breaks BOR
derivation.
All other flags in ADRS (ANL01FL, ABLFL, population flags from ADSL) follow the
standard "Y" or NA convention.
Common errors to avoid
- Using
rs instead of rs_onco_recist from pharmaversesdtm — the plain
rs object is no longer exported; the script will fail at load
- Using
case_when() or slice_min(AVAL) for BOR — manual BOR derivation
cannot replicate admiralonco's NE propagation rule and confirmation hierarchy;
always use derive_param_confirmed_bor()
- Not removing DOMAIN from RS before
derive_param_*() calls — causes
variable conflict errors; DOMAIN must be removed in Step 2, not in the final
select() at the end of the script
- Hardcoding
ref_confirm = 28 without a # REVIEW: comment — the
confirmation window is protocol-specific and must come from the SAP; a wrong
value silently inflates or deflates confirmed ORR
- Applying
derive_vars_dt() after derive_param_response() — ADT must
exist before the response parameter functions run; the functions use ADT for
confirmation window comparisons
- Using RANDDT as the clinical benefit anchor without verifying protocol
intent — if the protocol defines the 42-day window from the "first
qualifying response assessment" rather than randomization, a fixed RANDDT will
misclassify subjects
- Not printing the confirmed vs unconfirmed ORR comparison — the omission
is a silent audit risk; confirmed ORR > unconfirmed ORR indicates a
derivation error that will not surface without an explicit check
- Recoding CONFIRMED or CBRESPFL
"N" to NA — these values are
meaningful per the admiralonco function contract; recoding breaks downstream
BOR derivation
Output checklist
Before returning code, verify: