ADRS
Tumor Response Analysis Dataset
BASIC DATA STRUCTURE · one record per subject per parameter per assessment · keys STUDYID, USUBJID, PARAMCD, ASEQ
Variables
| Variable | Label | Type | Length | Derivation |
|---|---|---|---|---|
STUDYID | Study Identifier | text | Predecessor RS.STUDYID | |
USUBJID | Unique Subject Identifier | text | Predecessor RS.USUBJID | |
SUBJID | Subject Identifier for the Study | text | Predecessor ADSL.SUBJID | |
SITEID | Study Site Identifier | text | Predecessor ADSL.SITEID | |
AGE | Age | integer | 8 | Predecessor ADSL.AGE |
SEX | Sex | text | Predecessor ADSL.SEX | |
RACE | Race | text | Predecessor ADSL.RACE | |
TRT01P | Planned Treatment for Period 01 | text | Predecessor ADSL.TRT01P | |
TRT01PN | Planned Treatment for Period 01 (N) | integer | 8 | Predecessor ADSL.TRT01PN |
TRT01A | Actual Treatment for Period 01 | text | Predecessor ADSL.TRT01A | |
TRT01AN | Actual Treatment for Period 01 (N) | integer | 8 | Predecessor ADSL.TRT01AN |
SAFFL | Safety Population Flag | text | Predecessor ADSL.SAFFL | |
ITTFL | Intent-To-Treat Population Flag | text | Predecessor ADSL.ITTFL | |
RANDDT | Date of Randomization | integer | 8 | Predecessor ADSL.RANDDT |
ASEQ | Analysis Sequence Number | integer | 8 | Sequence number of the records of the RECIST 1.1 overall response and best overall response data of a subject, by PARAMCD, ADT, VISITNUM and RSSEQ. |
PARAMCD | Parameter Code | text | OVR for the overall response at each tumor assessment (RS.RSTESTCD = 'OVRLRESP' of the investigator, RECIST 1.1), and one record per subject for each response parameter: BOR and CBOR (best overall response without and with confirmation), RSP and CRSP (response), CB and CCB (clinical benefit), BCP, CBCP, PD, DEATH, LSTA and MDIS. | |
PARAM | Parameter | text | The response parameter's name, set with PARAMCD by the RECIST 1.1 response derivation, e.g. Best Overall Response by Investigator (confirmation not required). | |
PARCAT1 | Parameter Category 1 | text | Tumor Response; Reference Event for DEATH (RECIST 1.1 response parameters). | |
PARCAT2 | Parameter Category 2 | text | Investigator (the evaluator of the RECIST 1.1 overall response). | |
PARCAT3 | Parameter Category 3 | text | RECIST 1.1 (the response criteria of the overall response). | |
AVALC | Analysis Value (C) | text | The overall response (RS.RSSTRESC) at each assessment. For the parameters, by RECIST 1.1: the best overall response (CR, PR, SD at least 42 days after randomization, NON-CR/NON-PD, PD, NE; MISSING without one), confirmed when a CR or PR is followed by a CR (or CR/PR) at least 28 days later with at most one NE in between; Y or N for response, clinical benefit, progression, death and measurable disease. | |
AVAL | Analysis Value | integer | 8 | The overall response as a number (CR 1, PR 2, SD 3, NON-CR/NON-PD 4, PD 5, NE 6, MISSING 7); 1 or 0 for the Y/N response parameters (RECIST 1.1). |
ADT | Analysis Date | integer | 8 | Date of the assessment: RS.RSDTC converted, a missing day imputed to the last day of the month; for a response parameter the date of the assessment it comes from; DEATH: DTHDT (RECIST 1.1 response). |
ADTF | Analysis Date Imputation Flag | text | D when the day of the RECIST 1.1 overall response date was imputed. | |
AVISIT | Analysis Visit | text | RS.VISIT of the overall response assessment (of the assessment a response parameter comes from). | |
ANL01FL | Analysis Flag 01 | text | Y for the overall response assessments that count: on or after randomization, the worst one of a date (RECIST 1.1); Y on every response parameter. | |
ANL02FL | Analysis Flag 02 | text | Y for the overall response assessments up to and including the first PD (RECIST 1.1 response). | |
RSSEQ | Sequence Number | integer | 8 | Predecessor RS.RSSEQ |
RSTESTCD | Assessment Short Name | text | Predecessor RS.RSTESTCD | |
RSEVAL | Evaluator | text | Predecessor RS.RSEVAL | |
RSSTRESC | Assessment Result in Std Format | text | Predecessor RS.RSSTRESC | |
VISIT | Visit Name | text | Predecessor RS.VISIT | |
VISITNUM | Visit Number | float | 8 | Predecessor RS.VISITNUM |
RSDTC | Date/Time of Assessment | text | Predecessor RS.RSDTC |
Program adrs.sas
Version 1, written from Clinwright's patterns, 2026-10-17, checks passed.
/*==== 00-header ====*/
/*----------------------------------------------------------------------------
Data set : ADRS (Tumor Response Analysis Dataset)
Reporting effort : CSR
SDTM : RS
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 RS records, with the subject's TRTSDT, TRTEDT, SUBJID, SITEID, AGE, SEX, RACE, TRT01P, TRT01PN, TRT01A, TRT01AN, SAFFL, ITTFL, RANDDT from ADSL. */
proc sort data=sdtm.rs(keep=studyid usubjid rsseq rstestcd rsstresc rseval visitnum visit rsdtc) out=work._ds; by usubjid; run;
proc sort data=adam.adsl(keep=usubjid trtsdt trtedt subjid siteid age sex race trt01p trt01pn trt01a trt01an saffl ittfl randdt) out=work._adsl; by usubjid; run;
data work._ds;
merge work._ds(in=_in) work._adsl;
by usubjid;
if _in;
run;
/*==== 20-parameters ====*/
/* ADRS by RECIST 1.1 (investigator): the overall response at each assessment (OVR) and the response parameters
derived from it, with the rules of admiralonco (see SKILL.md).
Inputs: SDTM.RS (RSTESTCD OVRLRESP), SDTM.TU (target lesions at screening), ADAM.ADSL (RANDDT, DTHDT).
Output: WORK.ADRS, one record per subject per parameter (OVR: per assessment), with ADSL's variables. */
proc fcmp outlib=work.funcs.recist;
/* AVAL of a response: CR 1, PR 2, SD 3, NON-CR/NON-PD 4, PD 5, NE 6, MISSING 7. */
function resp_aval(resp $);
select (resp);
when ('CR') v = 1;
when ('PR') v = 2;
when ('SD') v = 3;
when ('NON-CR/NON-PD') v = 4;
when ('PD') v = 5;
when ('NE') v = 6;
when ('MISSING') v = 7;
otherwise v = .;
end;
return(v);
endsub;
/* Of several assessments on one date the worst counts; it sorts last. */
function resp_worst(resp $);
select (resp);
when ('NE') v = 1;
when ('CR') v = 2;
when ('PR') v = 3;
when ('SD') v = 4;
when ('NON-CR/NON-PD') v = 5;
when ('PD') v = 6;
otherwise v = 0;
end;
return(v);
endsub;
/* A date from ISO 8601 text, a missing day imputed to the month's last day (a missing month: no date). */
function dt_last_day(dtc $);
length part $ 10;
part = substr(strip(dtc), 1, 10);
result = .;
if length(part) = 10 then result = input(part, ?? yymmdd10.);
else if length(part) = 7 then result = intnx('month', input(cats(part, '-01'), ?? yymmdd10.), 0, 'end');
return(result);
endsub;
run;
options cmplib=work.funcs;
/* ---- Overall response at each assessment ------------------------------------------------------------------- */
proc sql;
create table _ovr as
select r.*, s.RANDDT as RANDDT
from sdtm.rs as r left join adam.adsl as s on r.STUDYID = s.STUDYID and r.USUBJID = s.USUBJID
where r.RSEVAL = 'INVESTIGATOR' and r.RSTESTCD = 'OVRLRESP';
quit;
data _ovr;
set _ovr;
length PARAMCD $ 8 PARAM $ 100 PARCAT1 PARCAT2 PARCAT3 $ 40 AVALC $ 20 AVISIT $ 40 ADTF $ 1;
PARAMCD = 'OVR';
PARAM = 'Overall Response by Investigator';
PARCAT1 = 'Tumor Response';
PARCAT2 = 'Investigator';
PARCAT3 = 'RECIST 1.1';
ADT = dt_last_day(RSDTC);
if not missing(ADT) and length(strip(RSDTC)) < 10 then ADTF = 'D';
AVISIT = VISIT;
AVALC = RSSTRESC;
AVAL = resp_aval(AVALC);
/* What counts: a response on or after randomization; of a date, the worst (below). */
_elig = not missing(AVAL) and not missing(ADT) and not missing(RANDDT) and ADT >= RANDDT;
_worst = resp_worst(AVALC);
format ADT RANDDT yymmdd10.;
run;
/* ANL01FL: the worst counting assessment of each date. */
proc sort data=_ovr;
by STUDYID USUBJID ADT _elig _worst RSSEQ;
run;
data _ovr;
set _ovr;
by STUDYID USUBJID ADT _elig _worst RSSEQ;
length ANL01FL ANL02FL $ 1;
if last.ADT and _elig then ANL01FL = 'Y';
run;
/* ANL02FL: assessments up to and including the first PD (all of them when there is none). */
proc sort data=_ovr;
by STUDYID USUBJID ADT RSSEQ;
run;
data _ovr;
set _ovr;
by STUDYID USUBJID;
retain _after_pd;
if first.USUBJID then _after_pd = 0;
if not _after_pd then ANL02FL = 'Y';
if AVALC = 'PD' then _after_pd = 1;
drop _after_pd _elig _worst;
run;
/* ---- Response parameters ----------------------------------------------------------------------------------- */
/* Each parameter is one assessment of the subject (or none): in the first kind of event that has one, its earliest
assessment, as admiralonco's derive_extreme_event chooses. A kind is a condition on assessment i:
d[i] its date, r[i] its response, conf[i] whether it is confirmed, rand the randomization date.
Macro comparisons are quoted: unquoted, a value like ne or or reads as an operator. */
%macro kind(kind);
%if "&kind" = "rsp" %then (r[i] in ('CR', 'PR'));
%else %if "&kind" = "cb" %then (r[i] in ('CR', 'PR', 'SD', 'NON-CR/NON-PD') and d[i] >= rand + 42);
%else %if "&kind" = "cr" %then (r[i] = 'CR');
%else %if "&kind" = "pr" %then (r[i] = 'PR');
%else %if "&kind" = "sd" %then (r[i] in ('CR', 'PR', 'SD') and d[i] >= rand + 42);
%else %if "&kind" = "noncrpd" %then (r[i] = 'NON-CR/NON-PD' and d[i] >= rand + 42);
%else %if "&kind" = "pd" %then (r[i] = 'PD');
%else %if "&kind" = "ne" %then (r[i] in ('CR', 'PR', 'SD', 'NON-CR/NON-PD', 'NE'));
%else %if "&kind" = "ccr" %then (r[i] = 'CR' and conf[i]);
%else %if "&kind" = "cpr" %then (r[i] = 'PR' and conf[i]);
%mend;
%macro value(kind);
%if "&kind" = "cr" or "&kind" = "ccr" %then 'CR';
%else %if "&kind" = "pr" or "&kind" = "cpr" %then 'PR';
%else %if "&kind" = "sd" %then 'SD';
%else %if "&kind" = "noncrpd" %then 'NON-CR/NON-PD';
%else %if "&kind" = "pd" %then 'PD';
%else %if "&kind" = "ne" %then 'NE';
%else 'Y';
%mend;
/* Kinds tried in turn (BOR, CBOR, RSP): the earliest assessment of the first kind that has one. */
%macro pick(param, kinds);
_p = "¶m";
_seq = .;
_val = '';
%do q = 1 %to %sysfunc(countw(&kinds, %str( )));
%let kind = %scan(&kinds, &q, %str( ));
if missing(_seq) then do i = 1 to n while (missing(_seq));
if %kind(&kind) then do;
_seq = s[i];
_val = %value(&kind);
end;
end;
%end;
output;
%mend;
/* Kinds that all mean "Y" (CB, CRSP, CCB): the earliest assessment of any of them. */
%macro pick_any(param, kinds);
_p = "¶m";
_seq = .;
_val = '';
do i = 1 to n while (missing(_seq));
if 0 %do q = 1 %to %sysfunc(countw(&kinds, %str( ))); or %kind(%scan(&kinds, &q, %str( ))) %end; then do;
_seq = s[i];
_val = 'Y';
end;
end;
output;
%mend;
%let maxa = 500;
data _picks(keep=STUDYID USUBJID _p _seq _val);
length _p $ 8 _val $ 20;
array d[&maxa] _temporary_;
array r[&maxa] $ 20 _temporary_;
array s[&maxa] _temporary_;
array conf[&maxa] _temporary_;
/* One subject's counting assessments (ANL01FL and ANL02FL), in date order. */
n = 0;
do until (last.USUBJID);
set _ovr(where=(ANL01FL = 'Y' and ANL02FL = 'Y') keep=STUDYID USUBJID ADT AVALC RSSEQ RANDDT ANL01FL ANL02FL);
by STUDYID USUBJID;
n + 1;
d[n] = ADT;
r[n] = AVALC;
s[n] = RSSEQ;
rand = RANDDT;
end;
/* Confirmed (crsp_y_cr, crsp_y_pr): a CR followed by a CR at least 28 days later, or a PR followed by a CR or PR at
least 28 days later; the assessments after it up to that one may only be CR/NE (for a CR) or CR/PR/NE (for a PR),
with at most one NE, and for a PR no PR after a CR. */
do i = 1 to n;
conf[i] = 0;
if r[i] in ('CR', 'PR') then do;
j = 0;
do k = i + 1 to n while (j = 0);
if d[k] >= d[i] + 28 and (r[k] = 'CR' or (r[i] = 'PR' and r[k] = 'PR')) then j = k;
end;
if j > 0 then do;
ok = 1;
ne = 0;
first_cr = .;
last_pr = .;
do k = i + 1 to j;
if r[i] = 'CR' and r[k] not in ('CR', 'NE') then ok = 0;
if r[i] = 'PR' and r[k] not in ('CR', 'PR', 'NE') then ok = 0;
ne + (r[k] = 'NE');
if r[k] = 'CR' and missing(first_cr) then first_cr = d[k];
if r[k] = 'PR' then last_pr = d[k];
end;
if ne > 1 then ok = 0;
if r[i] = 'PR' and not missing(first_cr) and not missing(last_pr) and first_cr <= last_pr then ok = 0;
conf[i] = ok;
end;
end;
end;
%pick(RSP, rsp)
%pick_any(CB, rsp cb)
%pick(BOR, cr pr sd noncrpd pd ne)
%pick_any(CRSP, ccr cpr)
%pick_any(CCB, ccr cpr cb)
%pick(CBOR, ccr cpr sd noncrpd pd ne)
run;
/* PD: the first progression among the assessments of ANL01FL. LSTA: the last of those assessments. */
data _picks2(keep=STUDYID USUBJID _p _seq _val);
length _p $ 8 _val $ 20;
set _ovr(where=(ANL01FL = 'Y'));
by STUDYID USUBJID;
retain _pd_seq;
if first.USUBJID then _pd_seq = .;
if AVALC = 'PD' and missing(_pd_seq) then do;
_pd_seq = RSSEQ;
_p = 'PD';
_seq = RSSEQ;
_val = 'Y';
output;
end;
if last.USUBJID then do;
_p = 'LSTA';
_seq = RSSEQ;
_val = AVALC;
output;
end;
run;
/* Every subject of ADSL gets every parameter: what was picked, or the value for none. */
data _params;
length _p $ 8 PARAM $ 100 PARCAT1 $ 40 _none $ 20 _aval $ 4;
input _p $ _none $ _aval $ PARCAT1 & $40. PARAM & $100.;
datalines;
BOR MISSING resp Tumor Response Best Overall Response by Investigator (confirmation not required)
BCP N yn Tumor Response Best Overall Response of CR/PR by Investigator (confirmation not required)
CB N yn Tumor Response Clinical Benefit by Investigator (confirmation for response not required)
CBCP N yn Tumor Response Best Confirmed Overall Response of CR/PR by Investigator
CBOR MISSING resp Tumor Response Best Confirmed Overall Response by Investigator
CCB N yn Tumor Response Confirmed Clinical Benefit by Investigator
CRSP N yn Tumor Response Confirmed Response by Investigator
DEATH N yn Reference Event Death
LSTA . none Tumor Response Last Disease Assessment by Investigator
MDIS N yn . Measurable Disease at Baseline by Investigator
PD N yn Tumor Response Disease Progression by Investigator
RSP N yn Tumor Response Response by Investigator (confirmation not required)
;
run;
/* MDIS: target lesions at screening (investigator). */
proc sql;
create table _mdis as
select distinct USUBJID
from sdtm.tu
where TUEVAL = 'INVESTIGATOR' and TUSTRESC = 'TARGET' and VISIT = 'SCREENING';
create table _d1 as
select a.STUDYID, a.USUBJID, a.DTHDT as DTHDT, p._p, p.PARAM, p.PARCAT1, p._aval,
coalesce(k._seq, k2._seq) as _seq,
case
when p._p = 'DEATH' then case when a.DTHDT is not missing then 'Y' else 'N' end
when p._p = 'MDIS' then case when m.USUBJID is not missing then 'Y' else 'N' end
else coalescec(k._val, k2._val, p._none)
end as _avalc length=20
from adam.adsl as a
cross join _params as p
left join _picks as k on k.USUBJID = a.USUBJID and k._p = p._p
left join _picks2 as k2 on k2.USUBJID = a.USUBJID and k2._p = p._p
left join _mdis as m on m.USUBJID = a.USUBJID;
quit;
/* BCP and CBCP follow BOR and CBOR: Y, with that assessment, when it is CR or PR.
(Data set options are applied in DATA steps: StatScript ignores them in SQL's FROM, OSI-0018.) */
data _bor(keep=USUBJID _bor _bor_seq) _cbor(keep=USUBJID _cbor _cbor_seq);
set _d1;
length _bor _cbor $ 20;
if _p = 'BOR' then do; _bor = _avalc; _bor_seq = _seq; output _bor; end;
if _p = 'CBOR' then do; _cbor = _avalc; _cbor_seq = _seq; output _cbor; end;
run;
proc sql;
create table _d2 as
select d.STUDYID, d.USUBJID, d.DTHDT, d._p, d.PARAM, d.PARCAT1, d._aval,
case when d._p = 'BCP' and b._bor in ('CR', 'PR') then b._bor_seq
when d._p = 'CBCP' and c._cbor in ('CR', 'PR') then c._cbor_seq
else d._seq end as _seq,
case when d._p = 'BCP' and b._bor in ('CR', 'PR') then 'Y'
when d._p = 'CBCP' and c._cbor in ('CR', 'PR') then 'Y'
else d._avalc end as _avalc length=20
from _d1 as d
left join _bor as b on b.USUBJID = d.USUBJID
left join _cbor as c on c.USUBJID = d.USUBJID;
quit;
/* A derived record takes the variables of the assessment it comes from. */
data _src;
set _ovr(drop=PARAMCD PARAM PARCAT1 AVALC AVAL ANL01FL rename=(STUDYID=_studyid USUBJID=_usubjid));
run;
proc sql;
create table _derived as
select d.STUDYID, d.USUBJID, d._p as PARAMCD length=8, d.PARAM, d.PARCAT1, d._aval, d._avalc, d.DTHDT, o.*
from _d2 as d left join _src as o on o._usubjid = d.USUBJID and o.RSSEQ = d._seq;
quit;
data _derived;
set _derived;
length AVALC $ 20 ANL01FL $ 1;
AVALC = _avalc;
ANL01FL = 'Y';
/* DEATH is a reference event, not an assessment. */
if PARAMCD = 'DEATH' then do;
ADT = DTHDT;
call missing(PARCAT2, PARCAT3);
end;
else do;
PARCAT2 = 'Investigator';
PARCAT3 = 'RECIST 1.1';
end;
if _aval = 'yn' then AVAL = ifn(AVALC = 'Y', 1, ifn(AVALC = 'N', 0, .));
else AVAL = resp_aval(AVALC);
drop _aval _avalc DTHDT _studyid _usubjid;
run;
/* ---- All records, their sequence, and ADSL's variables -------------------------------------------------------- */
data _all;
set _ovr _derived;
run;
proc sort data=_all;
by STUDYID USUBJID PARAMCD ADT VISITNUM RSSEQ;
run;
data _all;
set _all;
by STUDYID USUBJID;
if first.USUBJID then ASEQ = 0;
ASEQ + 1;
run;
/* ADSL's variables on every record: in a one-to-many merge a variable both have would keep ADSL's value only on a
subject's first record, so the records drop what ADSL brings (RANDDT). */
data work._ds;
merge _all(in=_in drop=RANDDT) adam.adsl;
by STUDYID USUBJID;
if _in;
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; %let _len14 = 1; %let _len15 = 1; %let _len16 = 1; %let _len17 = 1; %let _len18 = 1; %let _len19 = 1; %let _len20 = 1; %let _len21 = 1; %let _len22 = 1; %let _len23 = 1; %let _len24 = 1; %let _len25 = 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, 'TRT01P') > 0 then do; _ren = catx(' ', _ren, 'TRT01P=_rz7'); _asg = catx(' ', _asg, 'TRT01P = _rz7;');
_siz = catx(' ', _siz, '_len7 = max(_len7, lengthn(TRT01P));'); end;
if varnum(_dsid, 'TRT01A') > 0 then do; _ren = catx(' ', _ren, 'TRT01A=_rz8'); _asg = catx(' ', _asg, 'TRT01A = _rz8;');
_siz = catx(' ', _siz, '_len8 = max(_len8, lengthn(TRT01A));'); end;
if varnum(_dsid, 'SAFFL') > 0 then do; _ren = catx(' ', _ren, 'SAFFL=_rz9'); _asg = catx(' ', _asg, 'SAFFL = _rz9;');
_siz = catx(' ', _siz, '_len9 = max(_len9, lengthn(SAFFL));'); end;
if varnum(_dsid, 'ITTFL') > 0 then do; _ren = catx(' ', _ren, 'ITTFL=_rz10'); _asg = catx(' ', _asg, 'ITTFL = _rz10;');
_siz = catx(' ', _siz, '_len10 = max(_len10, lengthn(ITTFL));'); 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, 'PARCAT1') > 0 then do; _ren = catx(' ', _ren, 'PARCAT1=_rz13'); _asg = catx(' ', _asg, 'PARCAT1 = _rz13;');
_siz = catx(' ', _siz, '_len13 = max(_len13, lengthn(PARCAT1));'); end;
if varnum(_dsid, 'PARCAT2') > 0 then do; _ren = catx(' ', _ren, 'PARCAT2=_rz14'); _asg = catx(' ', _asg, 'PARCAT2 = _rz14;');
_siz = catx(' ', _siz, '_len14 = max(_len14, lengthn(PARCAT2));'); end;
if varnum(_dsid, 'PARCAT3') > 0 then do; _ren = catx(' ', _ren, 'PARCAT3=_rz15'); _asg = catx(' ', _asg, 'PARCAT3 = _rz15;');
_siz = catx(' ', _siz, '_len15 = max(_len15, lengthn(PARCAT3));'); end;
if varnum(_dsid, 'AVALC') > 0 then do; _ren = catx(' ', _ren, 'AVALC=_rz16'); _asg = catx(' ', _asg, 'AVALC = _rz16;');
_siz = catx(' ', _siz, '_len16 = max(_len16, lengthn(AVALC));'); end;
if varnum(_dsid, 'ADTF') > 0 then do; _ren = catx(' ', _ren, 'ADTF=_rz17'); _asg = catx(' ', _asg, 'ADTF = _rz17;');
_siz = catx(' ', _siz, '_len17 = max(_len17, lengthn(ADTF));'); end;
if varnum(_dsid, 'AVISIT') > 0 then do; _ren = catx(' ', _ren, 'AVISIT=_rz18'); _asg = catx(' ', _asg, 'AVISIT = _rz18;');
_siz = catx(' ', _siz, '_len18 = max(_len18, lengthn(AVISIT));'); end;
if varnum(_dsid, 'ANL01FL') > 0 then do; _ren = catx(' ', _ren, 'ANL01FL=_rz19'); _asg = catx(' ', _asg, 'ANL01FL = _rz19;');
_siz = catx(' ', _siz, '_len19 = max(_len19, lengthn(ANL01FL));'); end;
if varnum(_dsid, 'ANL02FL') > 0 then do; _ren = catx(' ', _ren, 'ANL02FL=_rz20'); _asg = catx(' ', _asg, 'ANL02FL = _rz20;');
_siz = catx(' ', _siz, '_len20 = max(_len20, lengthn(ANL02FL));'); end;
if varnum(_dsid, 'RSTESTCD') > 0 then do; _ren = catx(' ', _ren, 'RSTESTCD=_rz21'); _asg = catx(' ', _asg, 'RSTESTCD = _rz21;');
_siz = catx(' ', _siz, '_len21 = max(_len21, lengthn(RSTESTCD));'); end;
if varnum(_dsid, 'RSEVAL') > 0 then do; _ren = catx(' ', _ren, 'RSEVAL=_rz22'); _asg = catx(' ', _asg, 'RSEVAL = _rz22;');
_siz = catx(' ', _siz, '_len22 = max(_len22, lengthn(RSEVAL));'); end;
if varnum(_dsid, 'RSSTRESC') > 0 then do; _ren = catx(' ', _ren, 'RSSTRESC=_rz23'); _asg = catx(' ', _asg, 'RSSTRESC = _rz23;');
_siz = catx(' ', _siz, '_len23 = max(_len23, lengthn(RSSTRESC));'); end;
if varnum(_dsid, 'VISIT') > 0 then do; _ren = catx(' ', _ren, 'VISIT=_rz24'); _asg = catx(' ', _asg, 'VISIT = _rz24;');
_siz = catx(' ', _siz, '_len24 = max(_len24, lengthn(VISIT));'); end;
if varnum(_dsid, 'RSDTC') > 0 then do; _ren = catx(' ', _ren, 'RSDTC=_rz25'); _asg = catx(' ', _asg, 'RSDTC = _rz25;');
_siz = catx(' ', _siz, '_len25 = max(_len25, lengthn(RSDTC));'); 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 _len14 1 _len15 1 _len16 1 _len17 1 _len18 1 _len19 1 _len20 1 _len21 1 _len22 1 _len23 1 _len24 1 _len25 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);
call symputx('_len14', _len14);
call symputx('_len15', _len15);
call symputx('_len16', _len16);
call symputx('_len17', _len17);
call symputx('_len18', _len18);
call symputx('_len19', _len19);
call symputx('_len20', _len20);
call symputx('_len21', _len21);
call symputx('_len22', _len22);
call symputx('_len23', _len23);
call symputx('_len24', _len24);
call symputx('_len25', _len25);
end;
run;
data adam.adrs(label="Tumor Response 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"
TRT01P length=$&_len7 label="Planned Treatment for Period 01"
TRT01PN length=8 label="Planned Treatment for Period 01 (N)"
TRT01A length=$&_len8 label="Actual Treatment for Period 01"
TRT01AN length=8 label="Actual Treatment for Period 01 (N)"
SAFFL length=$&_len9 label="Safety Population Flag"
ITTFL length=$&_len10 label="Intent-To-Treat Population Flag"
RANDDT length=8 label="Date of Randomization" format=DATE9.
ASEQ length=8 label="Analysis Sequence Number"
PARAMCD length=$&_len11 label="Parameter Code"
PARAM length=$&_len12 label="Parameter"
PARCAT1 length=$&_len13 label="Parameter Category 1"
PARCAT2 length=$&_len14 label="Parameter Category 2"
PARCAT3 length=$&_len15 label="Parameter Category 3"
AVALC length=$&_len16 label="Analysis Value (C)"
AVAL length=8 label="Analysis Value"
ADT length=8 label="Analysis Date" format=DATE9.
ADTF length=$&_len17 label="Analysis Date Imputation Flag"
AVISIT length=$&_len18 label="Analysis Visit"
ANL01FL length=$&_len19 label="Analysis Flag 01"
ANL02FL length=$&_len20 label="Analysis Flag 02"
RSSEQ length=8 label="Sequence Number"
RSTESTCD length=$&_len21 label="Assessment Short Name"
RSEVAL length=$&_len22 label="Evaluator"
RSSTRESC length=$&_len23 label="Assessment Result in Std Format"
VISIT length=$&_len24 label="Visit Name"
VISITNUM length=8 label="Visit Number"
RSDTC length=$&_len25 label="Date/Time of Assessment"
;
set work._final&_ren;
&_asg
keep STUDYID USUBJID SUBJID SITEID AGE SEX RACE TRT01P TRT01PN TRT01A TRT01AN SAFFL ITTFL RANDDT ASEQ PARAMCD PARAM PARCAT1 PARCAT2 PARCAT3 AVALC AVAL ADT ADTF AVISIT ANL01FL ANL02FL RSSEQ RSTESTCD RSEVAL RSSTRESC VISIT VISITNUM RSDTC;
run;
proc sort data=adam.adrs; by STUDYID USUBJID PARAMCD ASEQ; run;
Data (first 20 of 4,950 records, simulated)
| STUDYID | USUBJID | SUBJID | SITEID | AGE | SEX | RACE | TRT01P | TRT01PN | TRT01A | TRT01AN | SAFFL | ITTFL | RANDDT | ASEQ | PARAMCD | PARAM | PARCAT1 | PARCAT2 | PARCAT3 | AVALC | AVAL | ADT | ADTF | AVISIT | ANL01FL | ANL02FL | RSSEQ | RSTESTCD | RSEVAL | RSSTRESC | VISIT | VISITNUM | RSDTC |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 1 | BCP | Best Overall Response of CR/PR by Investigator (confirmation not required) | Tumor Response | Investigator | RECIST 1.1 | Y | 1 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 2 | BOR | Best Overall Response by Investigator (confirmation not required) | Tumor Response | Investigator | RECIST 1.1 | PR | 2 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 3 | CB | Clinical Benefit by Investigator (confirmation for response not required) | Tumor Response | Investigator | RECIST 1.1 | Y | 1 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 4 | CBCP | Best Confirmed Overall Response of CR/PR by Investigator | Tumor Response | Investigator | RECIST 1.1 | Y | 1 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 5 | CBOR | Best Confirmed Overall Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | PR | 2 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 6 | CCB | Confirmed Clinical Benefit by Investigator | Tumor Response | Investigator | RECIST 1.1 | Y | 1 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 7 | CRSP | Confirmed Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | Y | 1 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 8 | DEATH | Death | Reference Event | N | 0 | Y | |||||||||||||
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 9 | LSTA | Last Disease Assessment by Investigator | Tumor Response | Investigator | RECIST 1.1 | PD | 5 | 2022-11-29 | WEEK 42 | Y | Y | 14 | OVRLRESP | INVESTIGATOR | PD | WEEK 42 | 16 | 2022-11-29 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 10 | MDIS | Measurable Disease at Baseline by Investigator | Investigator | RECIST 1.1 | Y | 1 | Y | ||||||||||||
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 11 | OVR | Overall Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | PR | 2 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 12 | OVR | Overall Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | PR | 2 | 2022-05-11 | WEEK 12 | Y | Y | 9 | OVRLRESP | INVESTIGATOR | PR | WEEK 12 | 6 | 2022-05-11 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 13 | OVR | Overall Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | PR | 2 | 2022-06-23 | WEEK 18 | Y | Y | 10 | OVRLRESP | INVESTIGATOR | PR | WEEK 18 | 8 | 2022-06-23 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 14 | OVR | Overall Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | PR | 2 | 2022-08-02 | WEEK 24 | Y | Y | 11 | OVRLRESP | INVESTIGATOR | PR | WEEK 24 | 10 | 2022-08-02 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 15 | OVR | Overall Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | PR | 2 | 2022-09-13 | WEEK 30 | Y | Y | 12 | OVRLRESP | INVESTIGATOR | PR | WEEK 30 | 12 | 2022-09-13 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 16 | OVR | Overall Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | PR | 2 | 2022-10-24 | WEEK 36 | Y | Y | 13 | OVRLRESP | INVESTIGATOR | PR | WEEK 36 | 14 | 2022-10-24 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 17 | OVR | Overall Response by Investigator | Tumor Response | Investigator | RECIST 1.1 | PD | 5 | 2022-11-29 | WEEK 42 | Y | Y | 14 | OVRLRESP | INVESTIGATOR | PD | WEEK 42 | 16 | 2022-11-29 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 18 | PD | Disease Progression by Investigator | Tumor Response | Investigator | RECIST 1.1 | Y | 1 | 2022-11-29 | WEEK 42 | Y | Y | 14 | OVRLRESP | INVESTIGATOR | PD | WEEK 42 | 16 | 2022-11-29 | |
| ONCO-EX | ONCO-EX-701002 | 701002 | 701 | 57 | F | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-02-11 | 19 | RSP | Response by Investigator (confirmation not required) | Tumor Response | Investigator | RECIST 1.1 | Y | 1 | 2022-03-23 | WEEK 6 | Y | Y | 8 | OVRLRESP | INVESTIGATOR | PR | WEEK 6 | 4 | 2022-03-23 | |
| ONCO-EX | ONCO-EX-701003 | 701003 | 701 | 58 | M | WHITE | Standard of Care | 1 | Standard of Care | 1 | Y | Y | 2022-03-16 | 1 | BCP | Best Overall Response of CR/PR by Investigator (confirmation not required) | Tumor Response | Investigator | RECIST 1.1 | N | 0 | Y |