Clinwright Public work of Helper Software LLC · free Start free

ADEX

Exposure Analysis Dataset

BASIC DATA STRUCTURE · one record per subject per parameter · keys STUDYID, USUBJID, PARAMCD

Variables

VariableLabelTypeLengthDerivation
STUDYIDStudy IdentifiertextPredecessor ADSL.STUDYID
USUBJIDUnique Subject IdentifiertextPredecessor ADSL.USUBJID
SUBJIDSubject Identifier for the StudytextPredecessor ADSL.SUBJID
SITEIDStudy Site IdentifiertextPredecessor ADSL.SITEID
AGEAgeinteger8Predecessor ADSL.AGE
SEXSextextPredecessor ADSL.SEX
RACERacetextPredecessor ADSL.RACE
SAFFLSafety Population FlagtextPredecessor ADSL.SAFFL
TRT01PPlanned Treatment for Period 01textPredecessor ADSL.TRT01P
TRT01AActual Treatment for Period 01textPredecessor ADSL.TRT01A
TRTAActual TreatmenttextPredecessor ADSL.TRT01A
TRTANActual Treatment (N)integer8Predecessor ADSL.TRT01AN
TRTSDTDate of First Exposure to Treatmentinteger8Predecessor ADSL.TRTSDT
TRTEDTDate of Last Exposure to Treatmentinteger8Predecessor ADSL.TRTEDT
PARAMCDParameter CodetextThe exposure parameters of each treated subject from the EX records: TRTDURD, NADMIN, CUMDOSE, DOSEINT, PDOSEINT, RDI, NDOSRED, NDOSINT (cumulative dose, dose intensity and relative dose intensity, dose reductions and interruptions).
PARAMParametertextTreatment Duration (days), Number of Administrations, Cumulative Dose, Dose Intensity, Planned Dose Intensity, Relative Dose Intensity (%), Number of Dose Reductions, Number of Dose Interruptions; doses in the unit of EX.EXDOSU.
AVALAnalysis Valuefloat8From the subject's EX records with a dose, in date order: the duration from the first dose to the last (+1 day; a dose every n days: the last administration + n days); the administrations (each day of a daily regimen, each record otherwise); the cumulative dose EX.EXDOSE times the administrations; dose intensity = cumulative dose / duration (per day for a daily regimen, per week otherwise); planned dose intensity from the first record's dose and frequency; relative dose intensity = 100 x dose intensity / planned; dose reductions: records with a lower dose than the one before; interruptions: a gap between records of a daily regimen, a dose more than half an interval late otherwise.
AVALUAnalysis Value UnittextThe unit of each exposure parameter's value: days for the duration, the dose unit (EX.EXDOSU) for the cumulative dose, per day or week for the dose intensity, % for the relative dose intensity, none for the counts.
ASEQAnalysis Sequence Numberinteger8Sequence number of the subject's records, sorted by PARAMCD.

Program adex.sas

Version 1, written from Clinwright's patterns, 2026-10-17, checks passed.

/*==== 00-header ====*/
/*----------------------------------------------------------------------------
  Data set : ADEX (Exposure Analysis Dataset)
  Reporting effort : CSR
  SDTM     : EX
  ADaM     : ADSL
  The header and the finalize step follow from the specification.
----------------------------------------------------------------------------*/
libname sdtm "/work/sdtm" access=readonly;
libname adam "/work/adam";
options validvarname=upcase nofmterr msglevel=i;

/*==== 10-inputs ====*/
/* The EX records, with the subject's TRTSDT, TRTEDT, STUDYID, USUBJID, SUBJID, SITEID, AGE, SEX, RACE, SAFFL, TRT01P, TRT01A, TRT01AN from ADSL. */
proc sort data=sdtm.ex(keep=studyid usubjid exdose exdosu exdosfrq exstdtc exendtc) out=work._ds; by usubjid; run;
proc sort data=adam.adsl(keep=usubjid trtsdt trtedt studyid usubjid subjid siteid age sex race saffl trt01p trt01a trt01an) out=work._adsl; by usubjid; run;
data work._ds;
  merge work._ds(in=_in) work._adsl;
  by usubjid;
  if _in;
  length trta $200;
  trta = trt01a;
  trtan = trt01an;
run;

/*==== 20-parameters ====*/
/* ADEX: each treated subject's exposure from SDTM.EX (records with a dose, placebo's 0 included), in date order:
   TRTDURD  treatment duration: first dose to last + 1 day (a dose every n days: the last administration + n days)
   NADMIN   administrations: each day of a daily regimen (QD; BID twice ...), each record otherwise
   CUMDOSE  cumulative dose: EXDOSE x the record's administrations
   DOSEINT  dose intensity: cumulative dose / duration, per day (daily regimen) or per week (none for single administrations)
   PDOSEINT planned dose intensity: the first record's dose by its frequency, in the same unit
   RDI      relative dose intensity (%): 100 x DOSEINT / PDOSEINT (none when nothing was planned: placebo)
   NDOSRED  dose reductions: records with a lower dose than the record before
   NDOSINT  interruptions: a gap between records of a daily regimen; an administration more than 0.5 of its
            interval late otherwise. */
data work._exrec;
  set sdtm.ex(keep=usubjid exdose exdosu exdosfrq exstdtc exendtc where=(not missing(exdose)));
  _st = input(substr(exstdtc, 1, 10), ?? yymmdd10.);
  _en = input(substr(exendtc, 1, 10), ?? yymmdd10.);
  if missing(_st) then delete;
  if missing(_en) or _en < _st then _en = _st;
  /* The regimen: administrations a day (daily), or the days between them. */
  select (upcase(strip(exdosfrq)));
    when ('QD', 'DAILY', 'Q24H') do; _every = 1; _perday = 1; end;
    when ('BID', 'Q12H') do; _every = 1; _perday = 2; end;
    when ('TID', 'Q8H') do; _every = 1; _perday = 3; end;
    when ('QID', 'Q6H') do; _every = 1; _perday = 4; end;
    when ('QW', 'Q1W', 'WEEKLY') do; _every = 7; _perday = 0; end;
    when ('Q2W', 'EVERY 2 WEEKS') do; _every = 14; _perday = 0; end;
    when ('Q3W', 'EVERY 3 WEEKS') do; _every = 21; _perday = 0; end;
    when ('Q4W', 'EVERY 4 WEEKS') do; _every = 28; _perday = 0; end;
    otherwise do; _every = 0; _perday = 0; end;
  end;
  if _every = 1 then _admin = (_en - _st + 1) * _perday;
  else _admin = 1;
run;
proc sort data=work._exrec; by usubjid _st; run;
data work._exp(keep=usubjid paramcd param aval avalu);
  set work._exrec;
  by usubjid;
  length paramcd $8 param $60 avalu $20 _unit $20 _per $10;
  retain _first _lastst _lasten _cum _n _red _int _prev _planned _plannedevery _plannedper _unit;
  if first.usubjid then do;
    _first = _st; _cum = 0; _n = 0; _red = 0; _int = 0; _prev = .; _lastst = .; _lasten = .;
    _planned = exdose; _plannedevery = _every; _plannedper = _perday; _unit = exdosu;
  end;
  _cum = _cum + exdose * _admin;
  _n = _n + _admin;
  if not missing(_prev) and exdose < _prev then _red = _red + 1;
  if not missing(_lastst) then do;
    if _plannedevery = 1 and _st > _lasten + 1 then _int = _int + 1;
    else if _plannedevery > 1 and _st - _lastst > _plannedevery * (1 + 0.5) then _int = _int + 1;
  end;
  _prev = exdose;
  _lastst = _st;
  _lasten = max(_lasten, _en);
  if last.usubjid then do;
    if _plannedevery > 1 then _dur = _lastst - _first + _plannedevery;
    else _dur = _lasten - _first + 1;
    /* Intensities per day for a daily regimen, per week otherwise. */
    if _plannedevery > 1 then do; _days = 7; _per = '/week'; end;
    else do; _days = 1; _per = '/day'; end;
    paramcd = 'TRTDURD'; param = 'Treatment Duration (days)'; aval = _dur; avalu = 'days'; output;
    paramcd = 'NADMIN'; param = 'Number of Administrations'; aval = _n; avalu = ''; output;
    paramcd = 'CUMDOSE'; param = cats('Cumulative Dose (', _unit, ')'); aval = _cum; avalu = _unit; output;
    /* Intensities for a regimen with a frequency (not single administrations). */
    if _plannedevery > 0 then do;
      paramcd = 'DOSEINT'; param = cats('Dose Intensity (', _unit, _per, ')'); aval = _cum / _dur * _days; avalu = cats(_unit, _per); output;
      if _plannedevery = 1 then _pdi = _planned * _plannedper;
      else _pdi = _planned / _plannedevery * 7;
      paramcd = 'PDOSEINT'; param = cats('Planned Dose Intensity (', _unit, _per, ')'); aval = _pdi; avalu = cats(_unit, _per); output;
      paramcd = 'RDI'; param = 'Relative Dose Intensity (%)'; avalu = '%';
      if _pdi > 0 then aval = 100 * (_cum / _dur * _days) / _pdi;
      else aval = .;
      output;
    end;
    paramcd = 'NDOSRED'; param = 'Number of Dose Reductions'; aval = _red; avalu = ''; output;
    paramcd = 'NDOSINT'; param = 'Number of Dose Interruptions'; aval = _int; avalu = ''; output;
  end;
run;
/* With the subject's variables (ADSL's): one record of each subject's (the records so far may be EX's). */
proc sort data=work._exp; by usubjid paramcd; run;
proc sort data=work._ds out=work._subj nodupkey; by usubjid; run;
data work._ds;
  merge work._exp(in=_in) work._subj;
  by usubjid;
  if _in;
run;

/*==== 80-sequence ====*/
/* ASEQ: 1, 2, ... per subject, by studyid  paramcd. */
proc sort data=work._ds; by usubjid studyid  paramcd; run;
data work._ds;
  set work._ds;
  by usubjid;
  if first.usubjid then aseq = 0;
  aseq + 1;
run;

/*==== 89-final ====*/
/* The data set as derived; the finalize step keeps the specification's variables. */
data work._final;
  set work._ds;
run;

/*==== 90-finalize ====*/
/* 90-finalize: from the specification; the variables, their order and attributes are not changed here. */
/* The text variables the specification gives no length: as long as their longest value (at least 1). */
%let _len1 = 1; %let _len2 = 1; %let _len3 = 1; %let _len4 = 1; %let _len5 = 1; %let _len6 = 1; %let _len7 = 1; %let _len8 = 1; %let _len9 = 1; %let _len10 = 1; %let _len11 = 1; %let _len12 = 1; %let _len13 = 1;
data _null_;
  length _ren _asg _siz $32767;
  _dsid = open('work._final');
  if varnum(_dsid, 'STUDYID') > 0 then do; _ren = catx(' ', _ren, 'STUDYID=_rz1'); _asg = catx(' ', _asg, 'STUDYID = _rz1;');
    _siz = catx(' ', _siz, '_len1 = max(_len1, lengthn(STUDYID));'); end;
  if varnum(_dsid, 'USUBJID') > 0 then do; _ren = catx(' ', _ren, 'USUBJID=_rz2'); _asg = catx(' ', _asg, 'USUBJID = _rz2;');
    _siz = catx(' ', _siz, '_len2 = max(_len2, lengthn(USUBJID));'); end;
  if varnum(_dsid, 'SUBJID') > 0 then do; _ren = catx(' ', _ren, 'SUBJID=_rz3'); _asg = catx(' ', _asg, 'SUBJID = _rz3;');
    _siz = catx(' ', _siz, '_len3 = max(_len3, lengthn(SUBJID));'); end;
  if varnum(_dsid, 'SITEID') > 0 then do; _ren = catx(' ', _ren, 'SITEID=_rz4'); _asg = catx(' ', _asg, 'SITEID = _rz4;');
    _siz = catx(' ', _siz, '_len4 = max(_len4, lengthn(SITEID));'); end;
  if varnum(_dsid, 'SEX') > 0 then do; _ren = catx(' ', _ren, 'SEX=_rz5'); _asg = catx(' ', _asg, 'SEX = _rz5;');
    _siz = catx(' ', _siz, '_len5 = max(_len5, lengthn(SEX));'); end;
  if varnum(_dsid, 'RACE') > 0 then do; _ren = catx(' ', _ren, 'RACE=_rz6'); _asg = catx(' ', _asg, 'RACE = _rz6;');
    _siz = catx(' ', _siz, '_len6 = max(_len6, lengthn(RACE));'); end;
  if varnum(_dsid, 'SAFFL') > 0 then do; _ren = catx(' ', _ren, 'SAFFL=_rz7'); _asg = catx(' ', _asg, 'SAFFL = _rz7;');
    _siz = catx(' ', _siz, '_len7 = max(_len7, lengthn(SAFFL));'); end;
  if varnum(_dsid, 'TRT01P') > 0 then do; _ren = catx(' ', _ren, 'TRT01P=_rz8'); _asg = catx(' ', _asg, 'TRT01P = _rz8;');
    _siz = catx(' ', _siz, '_len8 = max(_len8, lengthn(TRT01P));'); end;
  if varnum(_dsid, 'TRT01A') > 0 then do; _ren = catx(' ', _ren, 'TRT01A=_rz9'); _asg = catx(' ', _asg, 'TRT01A = _rz9;');
    _siz = catx(' ', _siz, '_len9 = max(_len9, lengthn(TRT01A));'); end;
  if varnum(_dsid, 'TRTA') > 0 then do; _ren = catx(' ', _ren, 'TRTA=_rz10'); _asg = catx(' ', _asg, 'TRTA = _rz10;');
    _siz = catx(' ', _siz, '_len10 = max(_len10, lengthn(TRTA));'); end;
  if varnum(_dsid, 'PARAMCD') > 0 then do; _ren = catx(' ', _ren, 'PARAMCD=_rz11'); _asg = catx(' ', _asg, 'PARAMCD = _rz11;');
    _siz = catx(' ', _siz, '_len11 = max(_len11, lengthn(PARAMCD));'); end;
  if varnum(_dsid, 'PARAM') > 0 then do; _ren = catx(' ', _ren, 'PARAM=_rz12'); _asg = catx(' ', _asg, 'PARAM = _rz12;');
    _siz = catx(' ', _siz, '_len12 = max(_len12, lengthn(PARAM));'); end;
  if varnum(_dsid, 'AVALU') > 0 then do; _ren = catx(' ', _ren, 'AVALU=_rz13'); _asg = catx(' ', _asg, 'AVALU = _rz13;');
    _siz = catx(' ', _siz, '_len13 = max(_len13, lengthn(AVALU));'); end;
  _rc = close(_dsid);
  if _ren ne '' then _ren = cats('(rename=(', _ren, '))');
  call symputx('_ren', _ren);
  call symputx('_asg', _asg);
  call symputx('_siz', _siz);
run;
data _null_;
  set work._final end=_end;
  retain _len1 1 _len2 1 _len3 1 _len4 1 _len5 1 _len6 1 _len7 1 _len8 1 _len9 1 _len10 1 _len11 1 _len12 1 _len13 1;
  &_siz
  if _end then do;
    call symputx('_len1', _len1);
    call symputx('_len2', _len2);
    call symputx('_len3', _len3);
    call symputx('_len4', _len4);
    call symputx('_len5', _len5);
    call symputx('_len6', _len6);
    call symputx('_len7', _len7);
    call symputx('_len8', _len8);
    call symputx('_len9', _len9);
    call symputx('_len10', _len10);
    call symputx('_len11', _len11);
    call symputx('_len12', _len12);
    call symputx('_len13', _len13);
  end;
run;
data adam.adex(label="Exposure Analysis Dataset");
  attrib
    STUDYID  length=$&_len1 label="Study Identifier"
    USUBJID  length=$&_len2 label="Unique Subject Identifier"
    SUBJID   length=$&_len3 label="Subject Identifier for the Study"
    SITEID   length=$&_len4 label="Study Site Identifier"
    AGE      length=8 label="Age"
    SEX      length=$&_len5 label="Sex"
    RACE     length=$&_len6 label="Race"
    SAFFL    length=$&_len7 label="Safety Population Flag"
    TRT01P   length=$&_len8 label="Planned Treatment for Period 01"
    TRT01A   length=$&_len9 label="Actual Treatment for Period 01"
    TRTA     length=$&_len10 label="Actual Treatment"
    TRTAN    length=8 label="Actual Treatment (N)"
    TRTSDT   length=8 label="Date of First Exposure to Treatment" format=DATE9.
    TRTEDT   length=8 label="Date of Last Exposure to Treatment" format=DATE9.
    PARAMCD  length=$&_len11 label="Parameter Code"
    PARAM    length=$&_len12 label="Parameter"
    AVAL     length=8 label="Analysis Value"
    AVALU    length=$&_len13 label="Analysis Value Unit"
    ASEQ     length=8 label="Analysis Sequence Number"
  ;
  set work._final&_ren;
  &_asg
  keep STUDYID USUBJID SUBJID SITEID AGE SEX RACE SAFFL TRT01P TRT01A TRTA TRTAN TRTSDT TRTEDT PARAMCD PARAM AVAL AVALU ASEQ;
run;
proc sort data=adam.adex; by STUDYID USUBJID PARAMCD; run;

Data (first 20 of 2,400 records, simulated)

STUDYIDUSUBJIDSUBJIDSITEIDAGESEXRACESAFFLTRT01PTRT01ATRTATRTANTRTSDTTRTEDTPARAMCDPARAMAVALAVALUASEQ
ONCO-EXONCO-EX-70100270100270157FWHITEYStandard of CareStandard of CareStandard of Care12022-02-122022-12-10CUMDOSECumulative Dose (mg/m2)975mg/m21
ONCO-EXONCO-EX-70100270100270157FWHITEYStandard of CareStandard of CareStandard of Care12022-02-122022-12-10DOSEINTDose Intensity (mg/m2/week)21.945337620578776mg/m2/week2
ONCO-EXONCO-EX-70100270100270157FWHITEYStandard of CareStandard of CareStandard of Care12022-02-122022-12-10NADMINNumber of Administrations153
ONCO-EXONCO-EX-70100270100270157FWHITEYStandard of CareStandard of CareStandard of Care12022-02-122022-12-10NDOSINTNumber of Dose Interruptions04
ONCO-EXONCO-EX-70100270100270157FWHITEYStandard of CareStandard of CareStandard of Care12022-02-122022-12-10NDOSREDNumber of Dose Reductions15
ONCO-EXONCO-EX-70100270100270157FWHITEYStandard of CareStandard of CareStandard of Care12022-02-122022-12-10PDOSEINTPlanned Dose Intensity (mg/m2/week)25mg/m2/week6
ONCO-EXONCO-EX-70100270100270157FWHITEYStandard of CareStandard of CareStandard of Care12022-02-122022-12-10RDIRelative Dose Intensity (%)87.7813504823151%7
ONCO-EXONCO-EX-70100270100270157FWHITEYStandard of CareStandard of CareStandard of Care12022-02-122022-12-10TRTDURDTreatment Duration (days)311days8
ONCO-EXONCO-EX-70100370100370158MWHITEYStandard of CareStandard of CareStandard of Care12022-03-172022-10-20CUMDOSECumulative Dose (mg/m2)825mg/m21
ONCO-EXONCO-EX-70100370100370158MWHITEYStandard of CareStandard of CareStandard of Care12022-03-172022-10-20DOSEINTDose Intensity (mg/m2/week)24.67948717948718mg/m2/week2
ONCO-EXONCO-EX-70100370100370158MWHITEYStandard of CareStandard of CareStandard of Care12022-03-172022-10-20NADMINNumber of Administrations113
ONCO-EXONCO-EX-70100370100370158MWHITEYStandard of CareStandard of CareStandard of Care12022-03-172022-10-20NDOSINTNumber of Dose Interruptions04
ONCO-EXONCO-EX-70100370100370158MWHITEYStandard of CareStandard of CareStandard of Care12022-03-172022-10-20NDOSREDNumber of Dose Reductions05
ONCO-EXONCO-EX-70100370100370158MWHITEYStandard of CareStandard of CareStandard of Care12022-03-172022-10-20PDOSEINTPlanned Dose Intensity (mg/m2/week)25mg/m2/week6
ONCO-EXONCO-EX-70100370100370158MWHITEYStandard of CareStandard of CareStandard of Care12022-03-172022-10-20RDIRelative Dose Intensity (%)98.71794871794872%7
ONCO-EXONCO-EX-70100370100370158MWHITEYStandard of CareStandard of CareStandard of Care12022-03-172022-10-20TRTDURDTreatment Duration (days)234days8
ONCO-EXONCO-EX-70100470100470160MWHITEYClinwrightinib 200 mgClinwrightinib 200 mgClinwrightinib 200 mg22022-03-182023-02-16CUMDOSECumulative Dose (mg)53600mg1
ONCO-EXONCO-EX-70100470100470160MWHITEYClinwrightinib 200 mgClinwrightinib 200 mgClinwrightinib 200 mg22022-03-182023-02-16DOSEINTDose Intensity (mg/day)159.52380952380952mg/day2
ONCO-EXONCO-EX-70100470100470160MWHITEYClinwrightinib 200 mgClinwrightinib 200 mgClinwrightinib 200 mg22022-03-182023-02-16NADMINNumber of Administrations3343
ONCO-EXONCO-EX-70100470100470160MWHITEYClinwrightinib 200 mgClinwrightinib 200 mgClinwrightinib 200 mg22022-03-182023-02-16NDOSINTNumber of Dose Interruptions14