James .M. Wanja. Last compiled on: March 11, 2022.
=============================================== ====== */
if macro variable is blank;
Check
=============================================== ====== */
=;
%let cond%put %sysevalf(%superq(cond)=,boolean);# 1- blank, 0 - not blank;
=============================================== ====== */
Is a dataset empty?
=============================================== ====== */
jw_empty(din=, lib=);
%macro
proc sql noprint;count(distinct subjectid) into :noobs
select &lib..&din. ;
from
quit;
%if &noobs eq 0 %then %do;
data _null_;
file print;"NOTE: No Observation in the Dataset";
put
run;
%end;
%mend jw_empty;jw_empty(din=, lib=); %
=============================================== ====== */
for the existence of a Dataset;
Checking
=============================================== ====== */
jw_exist(domain =,lib=rdb);
%macro %if %sysfunc(exist(&lib..&domain.)) %then
%do;
data _null_;/*directs PUT to write to the SAS print file*/
file print;"THE DATASET &domain EXISTS";
put
run;
%end;%else %do;
data _null_;
file print;"THE DATASET &domain. DOES NOT EXIST";;
put
run;
%end;
%mend jw_exist;
jw_exist(domain =,lib= ); %
=============================================== ====== */
-Ns[Denominators] through a tabulation
Macro Getting the BIG
=============================================== ====== */
jw_bigN(where=, cond=,data=,var= );
%macro %if &where = 'Y' %then
%do;= &data noprint;
proc freq data &var. /out=_bign(drop=percent rename=(count=bigN)) ;
tables &cond.;
where
run;
%end;%else %do;
= &data noprint;
proc freq data &var./out=_bign(drop=percent rename=(count=bigN)) ;
tables
run;
%end;= _bign;
proc sort data &var.;
by
run;
%mend jw_bigN;
jw_bigN(data=,cond=,where=,var=); %
=============================================== ====== */
- Computing INTERVALS between dates : INTCK, INTNX function
'CONTINUOUS' option in the INTCK function enables you to count the number of anniversaries
The
of one date that occur prior to a second date. For example, the statement= intck('year', '30APR1789'd, '04MAR1797'd, 'continuous');
Years
INTNX ( interval, from, n < , alignment > ) ;
- The INTCK function counts the number of interval boundaries between two date values
or between two datetime values=============================================== ====== */
= floor((intck("month", numbirth, numconsent) - (day(numconsent) < day(numbirth))) / 12);
age
= intck('year','01jan2009'd,'01jan2010'd);
years = intck('SEMIYEAR','01jan2009'd,'01jan2010'd);
SEMIYEAR = intck('qtr','01jan2009'd,'01jan2010'd);
quarters = intck('month','01jan2009'd,'01jan2010'd);
months = intck('week','01jan2009'd,'01jan2010'd);
weeks = intck('day','01jan2009'd,'01jan2010'd);
days
/*DateTime*/
= intck('hour','01jan2009:00:00:00'dt,'01jan2010:00:00:00'dt);
hours = intck('minute','01jan2009:00:00:00'dt,'01jan2010:00:00:00'dt);
minutes = intck('second','01jan2009:00:00:00'dt,'01jan2010:00:00:00'dt);
seconds
/*Time*/
= intck('hour','00:00:00't,'12:00:00't);
hours = intck('minute','00:00:00't,'12:00:00't);
minutes = intck('second','00:00:00't,'12:00:00't);
seconds
*Important notice! The INTCK functions does not count the number of complete intervals between two values.;
=intck('year','31dec2009'd,'01jan2010'd); /* This will give 1*/
years
* So USE!!!!!
'day365' paremeter tells to the INTCK function to multiply day by 365 times
The
;=intck('day365','31dec2009'd,'01jan2010'd); /* This will give 0*/ days365
* ================================ =============
: TWO-WAY Tabulation;
Categorical Variables Macrojw_bigN().
Assuming You have ran the macro above %
to give you _bign * ================================ =============
jw_cat2way(colvar=, rowvar= ,data=, where=, cond=,);
%macro
* The Tabulation;
%%if &where. = 'Y' %then %do;
= &data. noprint;
proc freq data &rowvar.*&colvar./ out=&data.1(drop=percent);
tables &cond.;
where
run;
%end;%else %do;
= &data. noprint;
proc freq data &rowvar.*&colvar./ out=&data.1(drop=percent);
tables
run;
%end;* sort;
%= &data.1;
proc sort data&rowvar.;
by
run;
* Get total... Cumulative sum;
%&data.2(drop=total);
data &data.1;
set &rowvar.;
by
retain total;if first.&rowvar. then total=0;
+count;
total
output;if last.&rowvar. then
do;= total;
count &colvar. = 'Total';
output;
end;* Sort by the colvar which will help merge with BigN;
%
proc sort;&colvar.;
by
run;
%* Merge with bigN to get %;
&data.3(drop = count perc);
data &data.2(in=a) _bign;
merge &colvar.;
by * Some formating ;
%= (count/bign)*100;
percent = put(round(percent,0.1),5.1);
perc = cat(put(count,4.0),' ','(',perc,')');
countper
drop percent bign;* sort by colvar to help in ransposing;
%if a;
proc sort;&rowvar.;
by
run;
* Transposing ;
%=&data.3 out=&data.4(drop=_name_);
proc transpose data&rowvar.;
by
var countper;&colvar.;
id
run;
* delete some ;
%=work nolist nodetails;
proc datasets library&data.1 &data.2 &data.3 ;
delete
run;
quit;
%mend jw_cat2way;
jw_cat2way(colvar=, rowvar= ,data=, where=, cond=,) %
*===================================================
- Calculating the stats
Continuous variables Macro 1 by/class variable
2 Variables
====================================================
;
;jw_contvar2(var1=,libr=,splitvar=,data=, var2=);
%macro
* Calculating the Numeric Stats ;
= &libr..&data. noprint nway mean;
proc means data&splitvar.;
class &var1. &var2.;
var = &libr.._stats1(drop = _type_ _freq_)
output out = n&var1.1 n&var2.1
n = mean&var1.1 mean&var2.1
mean = SD&var1.1 SD&var2.1
std = median&var1.1 median&var2.1
median= min&var1.1 min&var2.1
min = max&var1.1 max&var2.1
max = q1&var1.1 q1&var2.1
q1 = q3&var1.1 q3&var2.1
q3
;
run;
* formating the values ;
&libr.._stats2;
data &libr.._stats1;
set
*} n&var1.1 n&var2.1;
array n{*} $13 n&var1. n&var2.;
array n1{*} mean&var1.1 mean&var2.1;
array av{*} $13 mean&var1. mean&var2.;
array av1{*} SD&var1.1 SD&var2.1;
array std{*} $13 SD&var1. SD&var2.;
array std1{*} median&var1.1 median&var2.1;
array med{*} $13 median&var1. median&var2.;
array med1{*} min&var1.1 min&var2.1;
array min{*} $13 min&var1. min&var2.;
array min1{*} max&var1.1 max&var2.1;
array max{*} $13 max&var1. max&var2.;
array max1{*} q1&var1.1 q1&var2.1;
array q1{*} $13 q1&var1. q1&var2.;
array q11{*} q3&var1.1 q3&var2.1;
array q3{*} $13 q3&var1. q3&var2.;
array q31{
= 1 to dim(n);
do i if n{i} ne . then n1{i} = put(round(n{i},1),4.0);
if av{i} ne . then av1{i} = put(round(av{i},0.1),6.1);
if std{i} ne . then std1{i}= put(round(std{i},0.01),7.2);
if med{i} ne . then med1{i}= put(round(med{i},0.1),6.1);
if min{i} ne . then min1{i}= put(round(min{i},1),4.0);
if max{i} ne . then max1{i}= put(round(max{i},1),4.0);
if q1{i} ne . then q11{i} = put(round(q1{i},0.1),6.1);
if q3{i} ne . then q31{i} = put(round(q3{i},0.1),6.1);
end;&splitvar. n&var1.--q3&var2.;
keep
run;
* Transpose ;
=&libr.._stats2 out=&libr.._stats3(rename=(_name_=stat) drop=_label_);
proc transpose data
var _character_;&splitvar.;
id
run;
* some further formating:...checking cases ;
&libr.._stats4;
data $ 15.;
length grp &libr.._stats3;
set
if upcase(substr(stat,1,1))='N' then grp ='n';
if upcase(substr(stat,1,2))='SD' then grp ='SD';
if upcase(substr(stat,1,6))='MEDIAN' then grp ='Median';
if upcase(substr(stat,1,4))='MEAN' then grp ='Mean';
if upcase(substr(stat,1,3)) in ('MIN','MAX') then grp =propcase(substr(stat,1,3));
if upcase(substr(stat,1,2))='Q1' then grp ='Q1';
if upcase(substr(stat,1,2))='Q3' then grp ='Q3';
=lowcase(stat);
stat if find(stat,"&var1.")>1 then desc = "&var1." ;
if find(stat,"&var2.")>1 then desc = "&var2." ;
* A sorting variable ;
%if upcase(grp) = 'N' then order =1;
else if upcase(grp) = 'MEAN' then order =2;
else if upcase(grp) = 'SD' then order =3;
else if upcase(grp) = 'MIN' then order =4;
else if upcase(grp) = 'Q1' then order =5;
else if upcase(grp) = 'MEDIAN' then order =6;
else if upcase(grp) = 'Q3' then order =7;
else if upcase(grp) = 'MAX' then order =8;
drop stat;* Sorting by the grouping;
proc sort;
by desc order;
run;* delete some ;
%=work nolist nodetails;
proc datasets library&libr.._stats1 &libr.._stats2 &libr.._stats3;
delete
run;
quit;
%mend jw_contvar2;
jw_contvar2(var1=,var2= ,libr=,splitvar = ,data=); %
*===================================================
- Calculating the stats
Continuous variables Macro 1 by/class variable
1 Variables
====================================================
;
;jw_contvar1(var1=,libr=,splitvar=,data=);
%macro
* Calculating the Numeric Stats ;
= &libr..&data. noprint nway mean;
proc means data&splitvar.;
class &var1. ;
var = &libr.._stats1(drop = _type_ _freq_)
output out = n&var1.1
n = mean&var1.1
mean = SD&var1.1
std = median&var1.1
median= min&var1.1
min = max&var1.1
max
;
run;
* formating the values ;
&libr.._stats2;
data &libr.._stats1;
set
*} n&var1.1;
array n{*} $13 n&var1.;
array n1{*} mean&var1.1 ;
array av{*} $13 mean&var1. ;
array av1{*} SD&var1.1 ;
array std{*} $13 SD&var1.;
array std1{*} median&var1.1;
array med{*} $13 median&var1.;
array med1{*} min&var1.1;
array min{*} $13 min&var1.;
array min1{*} max&var1.1 ;
array max{*} $13 max&var1.;
array max1{
= 1 to dim(n);
do i if n{i} ne . then n1{i} = put(round(n{i},1),4.0);
if av{i} ne . then av1{i} = put(round(av{i},0.1),6.1);
if std{i} ne . then std1{i}= put(round(std{i},0.01),7.2);
if med{i} ne . then med1{i}= put(round(med{i},0.1),6.1);
if min{i} ne . then min1{i}= put(round(min{i},1),4.0);
if max{i} ne . then max1{i}= put(round(max{i},1),4.0);
end;&splitvar. n&var1.--max&var1.;
keep
run;
* Transpose ;
=&libr.._stats2 out=&libr.._stats3(rename=(_name_=stat) drop=_label_);
proc transpose data
var _character_;&splitvar.;
id
run;
* some further formating:...checking cases ;
&libr.._stats4;
data $ 15.;
length grp &libr.._stats3;
set
if upcase(substr(stat,1,1))='N' then grp ='n';
if upcase(substr(stat,1,2))='SD' then grp ='SD';
if upcase(substr(stat,1,6))='MEDIAN' then grp ='Median';
if upcase(substr(stat,1,4))='MEAN' then grp ='Mean';
if upcase(substr(stat,1,3)) in ('MIN','MAX') then grp =propcase(substr(stat,1,3));
=lowcase(stat);
stat if find(stat,"&var1.")>1 then desc = "&var1." ;
* A sorting variable ;
%if upcase(grp) = 'N' then order =1;
else if upcase(grp) = 'MEAN' then order =2;
else if upcase(grp) = 'SD' then order =3;
else if upcase(grp) = 'MEDIAN' then order =4;
else if upcase(grp) = 'MIN' then order =5;
else if upcase(grp) = 'MAX' then order =6;
drop stat;* Sorting by the grouping;
proc sort;
by desc order;
run;* delete some ;
%=work nolist nodetails;
proc datasets library&libr.._stats1 &libr.._stats2 &libr.._stats3;
delete
run;
quit;
%mend jw_contvar1;
jw_contvar1(var1=,libr=,splitvar = ,data=); %
* =========================================================
Add aditional rows
Add on to the contvar1 outputs* =========================================================;
data _stats5;$30 ;
length grp
set _stats4;
by desc;if missing(grp) then delete;
= cat(" ",grp);
grp
retain desc;*} grp--total;
array dd{
output;if last.desc then
do;missing(of dd{*});
call =.;
orderif (desc="cmdose" & missing(grp)) then grp="Fraction dose (Gy)";
if (desc="numfra" & missing(grp)) then grp="Number of fraction doses";
output;
end;* Sorting by the grouping;
proc sort;
by desc order; run;
='0' and regimen='Unknown';
creating a dataset with regimen
data rg;$20.;
input regimen
datalines;0
Unknown; run;
* ===================================================
* Epoch;
* ===================================================
*====== start macro epoch === ;
jw_epoch(sedata = ,
%macro datevar = ,
datanew=);
&datanew.1;
data &sedata.(keep = usubjid epoch sestdtc seendtc)
set &datanew.(keep=usubjid &datevar. rename=(&datevar.=sestdtc) in=a);
if a then flag=1;
proc sort;
by usubjid sestdtc flag;
run;*If there is a missing value of epoch use the previous observation;
%&datanew.2(keep=usubjid epoch &datevar.);
data &datanew.1;
set
by usubjid;
retain epoch1 end;if first.usubjid then epoch1= epoch;
if not missing(epoch) then
do;= epoch;
epoch1= input(sestdtc,anydtdte11.);
sest = input(seendtc,anydtdte11.);
end
end;else epoch = epoch1;
* - Ensure last out of range dates are not populated
%- Not expected though;
if (last.usubjid & flag=1 & sest>end) then epoch = '';
= &datevar.;
rename sestdtc if flag;
*sort;
%
proc sort;&datevar.;
by usubjid
run;
%mend jw_epoch;
*====== end macro epoch === ;
jw_epoch(sedata = sdtm., datevar = , datanew = ); %
* =========================================================
NO rEPoRt... * =========================================================;
noreport(dsin=RESULTS,out=yes,dsout=&output.);
%macro
data RESULTS;$ 40;
length col1 = '';
col1
output;= 'No Data to Report';
col1
output;= '';
col1
output;
run;%if %upcase(&out) = YES %then %do;
&dsout.;
data output.
set results;
run;
%end;=&dsin. nowindows headline headskip split='|' missing;
proc report data
column col1;/ " " style(column)=[cellwidth=80% just=c];
define col1
run;
%mend noreport;
/*Example*/
ds100(din=);
%macro * If there are NO observations;
%
proc sql noprint;count(distinct usubjid) into :noobs
select &din. ;
from
quit;%if &noobs eq 0 %then %do;
%rstart;
%noreport;
%rstop;
%end;%else %do;
%rstart;=&din. split='~' headline headskip center missing nowindows style(column)={asis=on};
proc report data
column col1 col2 col3 ;/ display "Subject ID" style={cellwidth=15% paddingright=1cm
define col1 =left asis=on};
just/ display "Analysis Population" style={cellwidth=25% paddingright=1cm
define col2 =left asis=on};
just/ display "Reason for Exclusion" style={cellwidth=50% paddingright=1cm
define col3 =left asis=on};
just
run;
%rstop;
%end; %mend ds100;
%rstart;
=output.cm201 nowd headline headskip split='~' style(report)=[fontsize=10pt] nocenter;
proc report dataregimen ('Number (%) of patients' a b c) order;
column / order noprint;
define order / display 'Number of regimens' left style(header)=[just=left]
define regimen style(column)=[cellwidth=4in cellspacing=10pt
=left asis=on];
just/ display "&arm_A~(N=&armcd_A)" left style(header)=[just=left]
define a style(column)=[cellwidth=1.5in cellspacing=10pt
=left asis=on];
just/ display "&arm_B~(N=&armcd_B)" left style(header)=[just=left]
define b style(column)=[cellwidth=1.5in cellspacing=10pt
=left asis=on];
just/ display "&arm_C~(N=&armcd_C)" left style(header)=[just=left]
define c style(column)=[cellwidth=1.5in cellspacing=10pt
=left asis=on];
just
compute after order;'';
line
endcomp;
run;
='^';
ods escapechar
=output.ex201 nowd headline headskip split='~' style(report)=[fontsize=12pt] nocenter missing;
proc report data
column duration name stat order;/ order noprint;
define order / display 'Treatment duration' style(header)=[just=left]
define duration style(column)=[cellwidth=4in asis=on ] flow;
/ display '' left style(header)=[just=left] style(column)=[cellwidth=3.5in
define name =left asis=on] flow;
just/ display "&cross_C.~(N=&n_c.)" left style(header)=[just=left]
define stat style(column)=[cellwidth=1.5in just=left asis=on] flow;
compute after order;'';
line
endcomp;
run;
/*
in a column;
Padding before or after or both --------------------------------------------
style(column)= {just=l leftmargin= 0.5in rightmargin= 0.5in}
ORstyle(column)= {just=l pretext=" " posttext=" "}
*/
%rstop;
* =============================================
+Main dataset
COMBINING SUPP
;
*==== Macro Start ====;
* Transpose supp to wide and merge with main dataset;
transpw(lib =,supp=,main= ,id =, id2=,);
%macro * sort supp and main;
%=&lib..&supp. out=_&supp.;
proc sort data&id.;
by usubjid
run;=&lib..&main. out=_&main.;
proc sort data&id2.;
by usubjid
run;* Transpose supp;
%= _&supp. out=_&supp.1(drop=_label_ _name_);
proc transpose data&id.;
by usubjid
var qval;
id qnam;
idlabel qlabel;
run;* Make --seq numeric;
%&supp.2(drop=idvarval);
data _&supp.1;
set _if not missing(&id.) then &id2. = input(&id.,8.);
proc sort;&id2.;
by usubjid
run;* Merge the two;
%&main.1;
data _&main. _&supp.2;
merge _&id2.;
by usubjid *rename &id2. seq;
run;* delete some ;
%=work nolist nodetails;
proc datasets library&main. _&supp. _&supp.1 _&supp.2;
delete _
run;
quit;
%mend transpw;*==== Macro End ====;
* ==============
+suppds
Merge ds
;transpw(lib=sdtm,supp=suppds,main=ds,id=idvarval,id2=dsseq); %
=raw._all_ nods;
proc contents data
run;=raw._all_ out=_sets(keep=name memname);
proc contents data
run;
=raw out=;
proc datasets lib*contents data=_all_;
quit; run;
* ============================================= ;
/* COmpress */
* ============================================= ;
jw_compress(din=,dout=);
%macro &dout.(keep=col:);
data &din.;
set *} $200 col: ;
array coln{= 1 to dim(coln);
do i = compress(tranwrd(coln{i},"*n",""));
coln{i}
end;
run;
%mend jw_compress;
jw_compress(din=_eff101c,dout=_eff101c1); %
* ============================================= ;
/* MAcro Variable */
* ============================================= ;
proc sql noprint;
select avisitn: tt separated by ' '
into
from tt; quit;
* ============================================= ;
if a Variable is in the dataset
Check
- returns the number of a variables position in a SAS data set, or 0 if the variable is not in the SAS data set.
VARNUM function - opens a SAS data set
OPEN
* ============================================= *
data test;$ count;
input fruit
datalines;12
apple 4
banana 5
coconut 7
date 9
eggs 5
fig
;
run;
data _null_;= open('test');
datasetid = varnum(datasetid,'count');
check = varnum(datasetid,'missingVar');
check2
if check = 0 then put 'Variable does not exist';
else put 'Variable does exists';
if check2 = 0 then put 'Variable does NOT exist';
else put 'Variable does exists';
run;
*===================================================
/s from raw variable
Check d.p
====================================================;
options mprint symbolgen;
jw_dps(din= , var=, cat="");
%macro
/* Check if Variable is Character.If Not.Convert it*/
vartype(keep=v);
data &din. ;
set = vtype(&var.);
v
proc sort nodupkey;
by v;
run;/*Store this is a macro var*/
proc sql noprint;unique(v) into :vtype from vartype;
select
run;&vtype.;
%put
/* If Var is already a character */
%if &vtype. = C %then %do;
&din.1(keep = dp: pre: &var. L: dcount);
data &din.;
set = scan(&var.,2,"."); /*get the numbers after the decimal*/
dp if dp = "" then dcount = 0;
else dcount = length(dp); /* get the length of the numbers after decimal point*/
/* d.p and precision for mean/median */
= (dcount+1);
dpmean = 1/(10**(dcount+1));
precm /* d.p and precision for sd/median */
= dcount+2;
dpsd = 1/(10**(dcount+2));
presd /* d.p and precision for max/min */
= dcount;
dpmin = 1/(10**(dcount));
precmin
/*To help with put widths:- use put(x,length.dp)*/
= lengthn(&var.);
L = L+1;
L2
run;
%end;%else %do;
&din.1(keep = dp: pre: var dcount L: fmt:);
data &din.;
set = strip(put(&var.,best.));
var = scan(var,2,"."); /*get the numbers after the decimal*/
dp if dp = "" then dcount = 0;
else dcount = length(dp); /* get the length of the numbers after decimal point*/
/* d.p and precision for mean/median */
= (dcount+1);
dpmean = 1/(10**(dcount+1));
precmean /* d.p and precision for sd/median */
= dcount+2;
dpsd = 1/(10**(dcount+2));
presd /* d.p and precision for max/min */
= dcount;
dpmin = 1/(10**(dcount));
precmin /* to help with put widths:- use put(x,length.dp)*/
= lengthn(var)+1;
L = L+1;
L2 /* formats */
= (L2 + dpmean) +(dpmean/10);
fmtmean = (L2 + dpsd) + (dpsd/10);
fmtsd
if dpmin = 0 then do;
= (L + dpmin) + (dpmin/10);
fmtmin = strip(put(fmtmin,4.0)) || "." ||"0";
fmtminc
end;else do;
= (L2 + dpmin) + (dpmin/10);
fmtmin = strip(put(fmtmin,5.1));
fmtminc
end;
run;
%end;
/*Get the max number of dp and put theat in a macro variable
Make these Macro Variables global.*/
proc sql noprint;
%global dpmin dpsd dpmean presd precmean precmin length fmtmean fmtsd fmtmin;max(dpmin) into :dpmin from &din.1;
select max(dpsd) into :dpsd from &din.1;
select max(dpmean) into :dpmean from &din.1;
select min(presd) into :presd from &din.1;
select min(precmin) into :precmin from &din.1;
select min(precmean) into :precmean from &din.1;
select max(L) into :length from &din.1;
select
/*infromats...To be used within put(,informat)*/
max(fmtmean) into :fmtmean from &din.1;
select max(fmtsd) into :fmtsd from &din.1;
select max(fmtminc) into :fmtmin from &din.1;
select
quit;
/* =================================================== */
/* Calculating the Numeric Stats */
= &din. noprint nway mean;
proc means data&var. ;
var = _stats1(drop = _type_ _freq_)
output out = n&var.1
n = mean&var.1
mean = SD&var.1
std = median&var.1
median= min&var.1
min = max&var.1
max
;
run;
/** formating the values */
data _stats2;
set _stats1;
*} n&var.1;
array n{*} $13 n&var.;
array n1{*} mean&var.1 ;
array av{*} $13 mean&var. ;
array av1{*} SD&var.1 ;
array std{*} $13 SD&var.;
array std1{*} median&var.1;
array med{*} $13 median&var.;
array med1{*} min&var.1;
array min{*} $13 min&var.;
array min1{*} max&var.1 ;
array max{*} $13 max&var.;
array max1{
= 1 to dim(n);
do i if n{i} ne . then n1{i} = put(round(n{i},1),4.0);
if av{i} ne . then av1{i} = put(round(av{i},&precmean.),&fmtmean.);
if std{i} ne . then std1{i}= put(round(std{i},&presd.),&fmtsd.);
if med{i} ne . then med1{i}= put(round(med{i},&precmean.),&fmtmean.);
if min{i} ne . then min1{i}= put(round(min{i},&precmin.),&fmtmin.);
if max{i} ne . then max1{i}= put(round(max{i},&precmin.),&fmtmin.);
end;*keep &splitvar. n&var1.--max&var1.;
%
run;
%mend jw_dps;
You need to use the options minoperator mindelimiter = “,”
/* =================================================== */
/* Using NOT IN in a macro */
/* =================================================== */
= ",";
options minoperator mindelimiter dummy();
%macro %if not %eval(&listofvisits in 122,124) %then %do;
data _dummyMonths;= " Month 12"; col2 = " 0"; ord2 = 3; ord1= 1; output;
col1
run;
%end;%else %do;
%end;
%mend;
/* =================================================== */
/* ===================================================
Read the NEXT OBServation./* =================================================== */
data have;$ Index Measure;
input ID
cards;1 11
A 2 12
A 3 13
A 1 21
B 2 22
B
;run;
data _nextObs;
set have;
by ID;have ( firstobs = 2 keep = Measure rename = (Measure = Next_Measure) )/*read in from line number 2*/
set have ( obs = 1 drop = _all_ );/*stop reading at line 1*/
= ifn(last.ID, (.), Next_Measure );
Next_Measure /*IFN(logical-expression, value-returned-when-true, value-returned-when-false <,value-returned-when-missing>)
similar to R ifelse*/
run;
* Get a sequence to label the yaxis. Limit this to 2dp;
data seq;= &min1. to &max1. by &by1.;
do i = round(i,0.01);
x
output;
end;
run;
proc sql noprint;
%global ylist;: ylist separated by " " from seq;
select x into quit;
Jw_rows(din=,rows=,dout=);
%macro &dout.;
data 8.;
length rows &din.;
set if _n_ in(&rows.);
= _n_;
rows
run; %mend Jw_rows;
mac_until();
%macro
proc sql;
select distinct trtgrp:trt_list separated by '!'
into
from pop_demo= 'Y';
where pnitt = &sqlobs;
%let num_trt
quit;&=trt_list &=num_trt;
%put = 1;
%let i %do %until (%scan(&trt_list, &i, !) eq );
%let trt_name = %scan(&trt_list, &i, !);
&=trt_name;
%put = train.demo;
proc means data = "&trt_name";
where trtgrp
var age;
run;%let i = %eval(&i + 1);
%end;
%mend;mac_until() %
proc sort nodupkeys;
by memname;
run;
proc sql noprint;count(distinct(memname)), memname as vars
select : nobs,
into: vars separated by '/'
from cont;
quit;
%macro uns;%do i = 1 %to &nobs;
%let d = %scan(%superq(vars),&i.,/);
&d._ ;
data &d. ;
set in (850);
where visitid
run; %end;
....
'dir "P:\PH19KTR\Kenya Assess 2020\Data\Analysis"';
filename pp pipe
data pp;$400;
length listing = reclen;
infile pp length $varying400. reclen;
input listing = prxparse("/\s?(\w+.sas7bdat)/");
re if prxmatch(re,listing) then do;
= prxposn(re,1,listing);
list
end; run;
*-- CMH;
= _cresp ;
proc freq data *biocon*trt01p*responder/cmh riskdiff(column=2 cl=(wald wilson) correct) alpha=0.10
table rastra1commonriskdiff(cl=(MH KLINGENBERG MR NEWCOMBE NEWCOMBEMR SCORE) column=2)
=_freq;
out= _cmh
ods output CMH = _common /*Common proportion difference*/
commonPdiff = _pdiffcl /*Proportion difference confidence limits*/
PdiffCLs = _riskdifcol2 /*Column 2 risk estimates*/
RiskDiffCol2 = _crostab(drop=_:)
CrossTabFreqs
; run;
* Computing 4 Measures of Association;
=Fitness pearson spearman kendall hoeffding
proc corr data=pearsn outs=spearmn outk=kendal outh=hoeff
outp=matrix(histogram);
plots
var Weight Oxygen RunTime;
run;
*plots=matrix(histogram); displays a symmetric matrix plot for the analysis variables
in the VAR statement
listed = output datasetss for the different statistics
out_
;
* Correlation analysis between two sets of variables:
- Sepal measurements (length & width) and the petal measurements (length & width);
=Setosa plots=matrix;
proc corr data
var sepallength sepalwidth;
with petallength petalwidth;
run;
* Compute Pearson & polyserial correlations;
=Fitness1 pearson polyserial
proc corr data=polyserl;
outpls
with Oxygen;
var Age Weight RunTime;
run;
* For the purpose of computing Pearson correlations, the variables in the
- WITH and VAR statements are treated as continuous variables.
* For the purpose of computing polyserial correlations, the variables in the:
- WITH statement are treated as ordinal variables by default,
- VAR statement are treated as continuous variables.
;
* Van der Waerden (Normal) Scores, Hodges-Lehmann estimate *
=_ses anova hl(refclass="Placebo") alpha=.05 vw median wilcoxon;
proc npar1way data
class trt01p;
var chg;
exact hl; / vw wilcoxon median ;
strata biostrat cdstrat
ods select VWStrata VWStrataTest VWScores VWTest WilcoxonScores HodgesLehmann;
run;
* Get the van der Waerden normal scores
= Option computes normal scores from the ranks.
NORMAL
;=_ses out=_sesRank normal=vw;
proc rank data
var chg;
ranks chg_rank; run;
ancova(din=);
%macro
= &din.(where=(20000<avisitn<=20012)) method = reml;
proc mixed data
class trt01p biostrat ; = biostrat trt01p base / solution ddfm=kr;
model chg / diff = control("Placebo") cl alpha=.10;
lsmeans trt01p = diffs_ancova
ods output diffs = lsmeans_ancova;
lsmeans
run;
%mend ancova;
mmrm_subgp(din=,cov=un,trt=trt01p, method=reml, bygp=);
%macro
= &din.(where=(20000<avisitn<=20012)) method = &method.;
proc mixed data &bygp.;
by &trt. avisitn biostrat usubjid ;
class = biostrat &trt. avisitn base &trt.*avisitn base*avisitn / solution ddfm=kr;
model chg / type=&cov. subject=usubjid;
repeated avisitn &trt.*avisitn /diff = control("Placebo" "20012") cl alpha=.10;
lsmeans = lsmeans_&bygp.(where=(avisitn=20012));
ods output lsmeans = diff_&bygp.(where=(avisitn=20012));
ods output diffs
run; %mend mmrm_subgp;
genmod(din=);
%macro *-Proc genmod;
%= &din. ;
proc genmod data trt01p(ref="Placebo") cdstrat biostrat /param=glm;
class responder(event="Yes") = trt01p cdstrat biostrat/type3 type1 alpha=0.1 dist=bin link=logit
model =20000 SCORING=20001;
lrci maxiter/diff =control("Placebo") oddsratio cl ilink alpha=0.1 exp;
lsmeans trt01p /*ods output diffs = _diff ;*/
run;
%mend genmod;
*-Proc logistic;
%
logistic(din=, firth="N",id=);
%macro
=&din.(where=(20000<avisitn<=20012));
proc logistic datatrt01p(ref="Placebo") cdstrat biostrat/param=glm;
class responder(event="Yes")= trt01p cdstrat biostrat/alpha=0.1 maxiter=20000 %if %upcase(&firth)=Y %then firth;;
model /diff=ref ;
oddsratio trt01p/diff =control("Placebo") oddsratio cl ilink alpha=0.1;
lsmeans trt01p = diffLogit_&id. ;
ods output diffs
run; %mend logistic;
/* ===================================================
EXACT/* =================================================== */
=_adeff1;
proc genmod data/*(ref="Sunitinib QD") strat1 strat2*// param=glm;
class trtpaval(event='1')= trtp /*strat1 strat2*// LRCI ITPRINT type3
model =bin link=logit;
dist
exact trtp;/ diff exp ilink cl ;%*for each trtp, estimate of the log odds of objective response;
lsmeans trtp'trt_effect' trtp 1 -1/exp ;
estimate /*ods output ExactOddsRatio = _OR;
= _paramEst;*/
ods output ExactParmEst = _midpval(keep= midpvalue test where=(test="Score"));
ods output ExactTests /*ods output Estimates = _Est(keep= label lbetaestimate --probchisq where=(label="Exp(trt_effect)")); %*Estimates of contrasts ;
=_lsdiff;
ods output Diffs =_lsmean;*/
ods output LSMeans
run;
* ============================================= ;
=work nolist nodetails;
proc datasets library:;
delete _
run; quit;