Macro %summary
1. Description
The SUMMARY macro is used to create summary statistics based on the given input variable(s). This macro will create a dataset finaltable in the work library after calculating the summary statistics based on the input variables. The percentage calculation is assumed to be computed based on population total N.
2. Dependencies
2.1 Global Macro Variables : INTABLE – The input dataset in which population count and percentage is calculated. TABLEFILT – The filer condition from input dataset in which population count and percentage is calculated.
2.2 Global Macros - N/A
3. Macro Parameters
Macro parameter | Description | Example |
---|---|---|
INDSIN (O) | The name of the input dataset which contains the variable for computing summary statistics. | INDSIN=ADAM.ADSL , Default value: None |
DSINFILT (O) | Any filter condition that needs to be applied in the input dataset. | DSINFILT=FASFL EQ ‘Y’ , Default value: None |
BY (O) | Specify the variable(s) required to compute the summary statistics. Two variables can be passed if we need to summarise results based on the second variable inside the values of the first variable. | BY=SEX , Default value: None |
BYFMT (O) | If a particular category from by variable needs to be presented with 0 counts, this parameter can be used. Also, we can use this parameter for sorting the values inside the by variables using another numeric format. | BYFMT=GENDER , Default value: None |
COLBY (R) | Specify the variable names corresponding to column headers in mock shell. | COLBY=TRT01A , Default value: None |
TRTFMT (O) | Intakes defined formats or to create dummy values inside columns when data is not present for all treatment groups as per mock shell. There should be a numeric format for ordering which should be specified in parameters, and a character format which has the same name as the numeric format and ends with suffix “s”. | TRTFMT=TRTN. , Default value: None |
SORTORDER (O) | If required to sort the values with a by variable, this parameter can be used. 1 is used to sort alphabetically and 2 is used to sort by decreasing incidence of total. | SORTORDER=1 , Default value: None |
DUPLICATE (O) | If the summary statistics needs to be taken based on some distinct values in the data, this parameter can set to Y. | DUPLICATE=Y , Default value: None |
DUPVAR (O) | If the summary statistics needs to be taken based on some distinct values in the data, this parameter can be used to specify the variable name. | DUPVAR=AESOC AEDECOD USUBJID , Default value: None |
DISPLAYTEXT (O) | The display style of variables in which summary statistics are computed. | DISPLAYTEXT=%STR(AGE (YEARS)) , Default value: None |
PERCENT (O) | In order to present the percentage corresponding to the summary count, set this parameter to Y. | PERCENT=Y , Default value: None |
ORD (R) | Used for traceability, pass the value 1 while calling the macro for first time, increment the value for each call. | ORD=1 , Default value: None |
APPEND (O) | Y/N option to append the output datasets from each macro call. If N, the dataset created from previous call is discarded and a new dataset is formed. | |
APPEND=N , Default value: None |
(R): Required (O): Optional
4. Assumptions
- The dataset and table filter for computing N should be defined as global macro parameter as INTABLE and TABLEFILT.
- All necessary formats must be specified before the macro call if required. There should be a numeric format for ordering which should be specified in this parameter and a character format which has the same name as numeric format and end with suffix “s”.
- The latest created dataset is considered as input dataset when INDSIN parameter is not specified.
- The macro will not handle the cases where more than two by variables are specified.
5. Sample Call
%SUMMARY(INDSIN= ADAM.ADSL,
DSINFILT= FASFL EQ "Y",
BY = SEX,
BYFMT= GENDER,
COLBY = TRT01A,
TRTFMT = TRTN,
DUPLICATE=N,
DUPVAR=,
DISPLAYTEXT = %NRSTR(SEX - N(%%)),
PERCENT= Y,
ORD = 3,
APPEND = Y);
%SUMMARY(INDSIN = ADAE,
DSINFILT = SAFFL EQ "Y" AND TRTEMFL EQ "Y",
BY = AESOC AEDECOD,
BYFMT =,
COLBY =TRT01A,
TRTFMT =,
SORTORDER = 2,
DUPLICATE = Y,
DUPVAR = AESOC AEDECOD USUBJID,
DISPLAYTEXT =,
PERCENT= Y,
ORD = 2,
APPEND = Y);
6. Macro Code
%macro summary(indsin=,
dsinfilt=,
by=,
byfmt=,
colby=,
trtfmt=,
sortorder=,
duplicate=,
dupvar=,
displaytext=,
percent=,
ord=,
append=);
ods select none;
/*VarExist macro is invoked to check if a particular variable exists in the dataset*/
%macro VarExist(ds, var);
%local rc dsid result;
%let dsid = %sysfunc(open(&ds));
%if %sysfunc(varnum(&dsid, &var)) > 0 %then %do;
%let result = 1;
%put NOTE: Var &var exists in &ds;
%end;
%else %do;
%let result = 0;
%put NOTE: Var &var not exists in &ds;
%end;
%let rc = %sysfunc(close(&dsid));
&result
%mend VarExist;
/*Checking if indsin parameter is specified. Giving a user info otherwise*/
%if %str(&indsin.) eq %str() %then
%do;
%let indsin = &syslast.;
%put INFO:Since input dataset parameter is not given, latest created dataset has been taken.;
%end;
/*Creating the input dataset in work library. cntvar is created as a dummay variable for count calculation*/
%if %sysfunc(countw(&indsin.,%str(.))) eq 2 %then %do;
data __%scan(&indsin.,2,%str(.));
set &indsin.;
cntvar=1;
run;
%let dsin = %scan(&indsin.,2,%str(.));
%end;
%else %do;
data __&indsin.;
set &indsin.;
cntvar=1;
run;
%let dsin = &indsin.;
%end;
/*if format is specified for by variable, the decoded format is presented in the data*/
%if %str(&byfmt.) ne %str() %then %do;
data __&dsin.;
length &by. $200.;
format &by. $200.;
informat &by. $200.;
set __&dsin.;
&by. = strip(put(&by.,$&byfmt..));
run;
%end;
/*Setting up the macro variable for N and percentage calculation*/
%if %sysfunc(countw(&intable.,%str(.))) eq 2 %then %do;
data pop_%scan(&intable.,2,%str(.));
set &intable.;
run;
%let table = pop_%scan(&intable.,2,%str(.));
%end;
%else %do;
data pop_&intable.;
set &intable.;
run;
%let table = pop_&intable.;
%end;
/*Checking if the required parameters have missing values*/
%if %str(&colby.) eq %str() %then
%do;
%put %str(WAR)NING: Required parameter colby is not given.Kindly update.;
%abort;
%end;
%if %str(&ord.) eq %str() %then
%do;
%put %str(WAR)NING: Required parameter ord is not given.Kindly update.;
%abort;
%end;
/*Checking if the by variable have more than 2 values present*/
%if %str(&by.) ne %str() %then
%do;
%if %sysfunc(countw(&by.)) ge 3 %then
%do;
%put %str(WAR)NING: Macro will not be handled for more than 2 by variables.Program Manually.;
%abort;
%end;
%end;
/*Checking if the duplicate parameter is specified as Y and duplicates are removed accordingly*/
%if %str(&duplicate.) eq %str(Y) %then
%do;
%if %str(&by.) eq %str() %then
%do;
proc sort data = __&dsin.(where=(&dsinfilt.)) out = __&dsin.1_a nodupkey;
by &colby.n &colby. &dupvar.;
run;
%end;
%else %if %sysfunc(countw(&by.)) eq 1 %then
%do;
proc sort data = __&dsin.(where=(&dsinfilt.)) out = __&dsin.1_a nodupkey;
by &colby.n &colby. &dupvar.;
run;
%end;
%else
%do;
proc sort data = __&dsin.(where=(&dsinfilt.)) out = __&dsin.1_a1 nodupkey;
by &colby.n &colby. %scan(&dupvar.,1,%str( )) %scan(&dupvar.,3,%str( ));
run;
proc sort data = __&dsin.(where=(&dsinfilt.)) out = __&dsin.1_a2 nodupkey;
by &colby.n &colby. %scan(&dupvar.,1,%str( )) %scan(&dupvar.,2,%str( )) %scan(&dupvar.,3,%str( ));
run;
%end;
%end;
/*If there are no duplicate values needs to be removed, dataset is sorted accordingly*/
%else
%do;
%if %str(&by.) eq %str() %then
%do;
data __&dsin.1_a;
set __&dsin.(where=(&dsinfilt.));
run;
%end;
%else
%do;
proc sort data = __&dsin.(where=(&dsinfilt.)) out = __&dsin.1_a;
by &by.;
run;
%end;
%end;
%if %sysfunc(exist(__&dsin.1_a)) %then %do;
proc sort data = __&dsin.1_a;
by &colby.n &colby. %if %str(&by.) ne %str( ) %then %do;
%if %sysfunc(countw(&by.)) eq 1 %then %do;
%if %varexist(__&dsin.,&by.n) %then %do; &by.n %end; %end; %end; &by.;
run;
%end;
/*Summary is calculated using proc means if there are no by variables, cntvar variable is used for summary */
%if %str(&by.) eq %str() %then
%do;
proc means data = __&dsin.1_a completetypes noprint;
class &colby.n %if
/*Preloadfmt option is used to present dummy column headers*/
%str(&trtfmt.) ne %str() %then %do;/preloadfmt %end; ;
%if %str(&trtfmt.) ne %str() %then %do;
format &colby.n &trtfmt..;
%end;
var cntvar;
output out = __&dsin._1(where=(_type_ ne 0)) n=count;
run;
%end;
/*Summary is calculated using proc means if 1 by variables, cntvar variable is used for summary */
%else %if %sysfunc(countw(&by.)) eq 1 %then
%do;
proc sort data = __&dsin.1_a;
by %if %varexist(__&dsin.,&by.n) %then %do; &by.n %end; &by.;
run;
proc means data = __&dsin.1_a completetypes noprint;
by %if %varexist(__&dsin.,&by.n) %then %do; &by.n %end; &by.;
class &colby.n %if
%str(&trtfmt.) ne %str() %then %do;/preloadfmt %end; ;
%if %str(&trtfmt.) ne %str() %then %do;
format &colby.n &trtfmt..;
%end;
var cntvar;
output out = __&dsin._1(where=(_type_ ne 0)) n=count;
run;
%end;
/*If there are 2 by variables present, summary is taken for both of the variable together*/
%else
%do;
proc sort data = __&dsin.1_a2;
by &by.;
run;
proc means data = __&dsin.1_a2 completetypes noprint;
by &by.;
class &colby.n %if
%str(&trtfmt.) ne %str() %then %do;/preloadfmt %end; ;
%if %str(&trtfmt.) ne %str() %then %do;
format &colby.n &trtfmt..;
%end;
var cntvar;
output out = __&dsin._1a1(where=(_type_ ne 0)) n=count;
run;
proc sort data = __&dsin.1_a1;
by %scan(&by.,1,%str( ));
run;
/*If there are 2 by variables present, summary is taken for the first by variable*/
proc means data = __&dsin.1_a1 completetypes noprint;
by %scan(&by.,1,%str( ));
class &colby.n %if
%str(&trtfmt.) ne %str() %then %do;/preloadfmt %end; ;
%if %str(&trtfmt.) ne %str() %then %do;
format &colby.n &trtfmt..;
%end;
var cntvar;
output out = __&dsin._1a2(where=(_type_ ne 0)) n=count;
run;
proc sort data = __&dsin._1a2;
by %scan(&by.,1,%str( ));
run;
proc sort data = __&dsin._1a1;
by %scan(&by.,1,%str( )) %scan(&by.,2,%str( ));
run;
/*Setting the dataset contains summary of both by variables*/
data __&dsin._1a3;
set __&dsin._1a2 __&dsin._1a1;
by %scan(&by.,1,%str( ));
run;
proc sort data = __&dsin._1a3 out = __&dsin._1a4;
by descending &colby.n %scan(&by.,1,%str( )) %scan(&by.,2,%str( ));
run;
%end;
/*The final dataset created from the if conditions are identified and stored in __&dsin._1*/
data __&dsin._1;
set &syslast.;
run;
%let nobs = &sysnobs.;
/*Identifying the distinct values of column headers*/
proc sort data = &table.(where=(&tablefilt.)) out = &table._1 nodupkey;
by &colby.n;
run;
proc sql;
create table fmtt2 as select * from sashelp.vformat where upcase(libname) eq "WORK";
quit;
%let fmtobs = &sysnobs.;
/*Looking for all the necessary formats in work library*/
%if %str(&trtfmt.) ne %str() and &fmtobs. gt 0 %then %do;
proc format library=work.formats cntlout=fmtt;
run;
proc sql noprint;
select strip(label) into: headvar separated by "**" from fmtt where upcase(fmtname) eq "%upcase(&trtfmt.)";
select strip(label) into: headvarlb separated by "**" from fmtt where upcase(fmtname) eq "%upcase(&trtfmt.S)";
quit;
%end;
/*Geeting the numeric value and label of column headers into macro variables*/
%else %do;
proc sql noprint;
select &colby.n into : headvar separated by "**" from &table._1;
select &colby. into : headvarlb separated by "**" from &table._1;
quit;
%end;
/*Geeting the total count into different macro variables based on treatment groups*/
proc sql noprint;
select count(*) into : tot from &table. where &tablefilt.;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
select count(*) into :div&i. from &table. where &tablefilt. and &colby.n eq %scan(&headvar.,&i.,%str(**));
%let divname&i. = _%scan(&headvar.,&i.,%str(**));
%end;
quit;
/*Processing formats for by variables*/
%if %str(&by.) ne %str() %then
%do;
%if &fmtobs. gt 0 %then %do;
proc format library=work.formats cntlout=fmtt;
run;
data fmtt1;
set fmtt;
where upcase(fmtname) eq "%upcase(&byfmt.n)";
run;
%if &sysnobs. gt 0 %then
%do;
/*Aborting the macro if formats specified for more than 1 by variable*/
%if %sysfunc(countw(&by.)) gt 1 %then
%do;
%put %str(WAR)NING : Macro will not be processed since byfmt is present for more than one by variable.;
%abort;
%end;
/*Aborting the macro if the numeric variable for the by variable not present*/
%if %varexist(__&dsin.,&by.n) eq 0 %then
%do;
%put %str(WAR)NING: &by. variable is present, but &by.n variable is not present.;
%abort;
%end;
proc sort data = __&dsin. out = __&dsin._a(keep=&by. &by.n) nodupkey;
by &by. &by.n;
run;
/*Creating a dummy dataset for all the values in by variables from the macro parameter byfmt*/
proc format library=work.formats cntlout=fmtt;
run;
%let numlb=;
%let deslb=;
proc sql noprint;
select strip(start) into: numlb separated by "**" from fmtt where upcase(fmtname) eq "%upcase(&byfmt.n)";
select strip(label) into: deslb separated by "**" from fmtt where upcase(fmtname) eq "%upcase(&byfmt.n)";
quit;
data __&dsin._dummy;
length &by. $200.;
%do i = 1 %to %sysfunc(countw(%quote(&numlb.),%str(**)));
&by. = "%scan(%quote(&deslb.),&i.,%str(**))";
&by.n = %scan(%quote(&numlb.),&i.,%str(**));
output;
%end;
run;
proc sort data = __&dsin._dummy nodupkey;
by &by. &by.n;
run;
/*Count is assigned to 0 for the dummy dataset created for by variables*/
data __&dsin._dummy_final;
length &colby.n 8.;
set %do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
__&dsin._dummy(in=a&i.) %end;;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
if a&i. then
do;
&colby.n = %scan(&headvar.,&i.,%str(**));
_count = 0;
output;
end;
%end;
run;
proc sort data = __&dsin._1;
by &colby.n &by.n;
run;
proc sort data = __&dsin._dummy_final;
by &colby.n &by.n;
run;
/*Merging the summary dataset and dummy dataset to get all the required combinations*/
data __&dsin._2;
length &by. $200. &colby.n 8. ;
merge __&dsin._1 __&dsin._dummy_final;
by &colby.n &by.n;
run;
data __&dsin._3a(drop=_count);
set __&dsin._2;
count = coalesce(count,_count);
run;
%end;
%else %do;
data __&dsin._3a;
set __&dsin._1;
run;
%end;
%end;
%else
%do;
data __&dsin._3a;
set __&dsin._1;
run;
%end;
/*Processing the dataset having 1 by variable for the transposing*/
%if %sysfunc(countw(&by.)) ne 2 %then
%do;
proc sort data = __&dsin._3a;
by %if %varexist(__&dsin.,&by.n) %then %do; &by.n %end; &by.;
run;
proc transpose data = __&dsin._3a out = __&dsin._3b(drop=_name_ %if %varexist(__&dsin.,&by.n) %then %do; &by.n %end;);
by %if %varexist(__&dsin.,&by.n) %then %do; &by.n %end; &by.;
id &colby.n;
var count;
run;
%end;
/*Processing the dataset having 2 by variable for the transposing*/
%else
%do;
proc sort data = __&dsin._3a;
by %scan(%str(&by.),1,%str( )) %scan(%str(&by.),2,%str( ));
run;
proc transpose data = __&dsin._3a out = __&dsin._3b(drop=_name_ );
by %scan(%str(&by.),1,%str( )) %scan(%str(&by.),2,%str( ));
id &colby.n;
var count;
run;
%end;
/*Identifying the different variables in __&dsin._3b other than by variables that can be used for total calculation*/
proc sql noprint;
select distinct(name) into:sumvar1 separated by " " from dictionary.columns where
lowcase(libname) eq "work" and lowcase(memname) eq "%lowcase(__&dsin._3b)" and
%if %sysfunc(countw(&by.)) eq 1 %then %do; lowcase(name) ne "%lowcase(&by.)";%end;
%else %do; lowcase(name) not in ("%lowcase(%scan(&by.,1,%str( )))","%lowcase(%scan(&by.,2,%str( )))"); %end;
quit;
/*Setting 0 value to all the treatment headers as a dummy*/
data __&dsin._head;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
_%scan(&headvar.,&i.,%str(**)) = 0;
%end;
run;
data __&dsin._3c;
merge __&dsin._3b __&dsin._head(drop=&sumvar1.);
run;
data __&dsin._3a;
set __&dsin._3c;
run;
/*Handling the dataset for 1 by variable, missing values are treated as 0*/
%if %sysfunc(countw(&by.)) eq 1 %then
%do;
data __&dsin._3a;
length &by. $200.;
format &by. $200.;
informat &by. $200.;
set __&dsin._3c;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
if missing(_%scan(&headvar.,&i.,%str(**))) then
_%scan(&headvar.,&i.,%str(**)) = 0;
%end;
%if %nrbquote(&displaytext.) ne %str() %then %do;
&by. = cat(" ",strip(&by.));
%end;
run;
%end;
%end;
/*If there are no by variables, dataset is formatted accordingly to display count*/
%else %if %str(&by.) eq %str() %then
%do;
%if &nobs. gt 0 %then
%do;
data __&dsin._2;
set __&dsin._1;
statistic = "%nrbquote(&displaytext.)";
run;
proc transpose data = __&dsin._2 out = __&dsin._3(drop=_name_ );
by statistic;
id &colby.n;
var count;
run;
proc sql noprint;
select distinct(name) into:sumvar1 separated by " " from dictionary.columns where
lowcase(libname) eq "work" and lowcase(memname) eq "%lowcase(__&dsin._3)" and
name not in ("statistic","_99");
quit;
data __&dsin._head;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
_%scan(&headvar.,&i.,%str(**)) = 0;
%end;
run;
data __&dsin._3a;
merge __&dsin._3 __&dsin._head(drop=&sumvar1.);
run;
%end;
/*Handling categories with no observations to present it as 0*/
%else
%do;
data __&dsin._3;
statistic = "%nrbquote(&displaytext.)";
run;
data __&dsin._head;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
_%scan(&headvar.,&i.,%str(**)) = 0;
%end;
run;
data __&dsin._3a;
merge __&dsin._3 __&dsin._head;
run;
%end;
%end;
/*Formatting the final dataset if no by variables present*/
%if %str(&by.) ne %str() %then
%do;
%if %sysfunc(countw(&by.)) eq 1 %then
%do;
data dummy__;
statistic = "%nrbquote(&displaytext.)";
run;
data __&dsin._3a;
length statistic $400.;
set %if %nrbquote(&displaytext.) ne %str() %then %do; dummy__ %end; __&dsin._3a(rename=(&by.=statistic));
run;
%end;
%end;
/*When 2 by variables are specified, identifying the columns in which total needs to be calculated*/
proc sql noprint;
select distinct(name) into:sumvar separated by "," from dictionary.columns where
lowcase(libname) eq "work" and lowcase(memname) eq "%lowcase(__&dsin._3a)" and
lowcase(name) ne "statistic" %if %str(&by.) ne %str() %then %do;
and lowcase(name) not in ("%lowcase(%scan(&by.,1,%str( )))","%lowcase(%scan(&by.,2,%str( )))") %end;;
quit;
/*Calculating the total*/
data __&dsin._4;
set __&dsin._3a;
%if %str(&by.) eq %str() %then
%do;
totaln = sum(&sumvar.);
%end;
%else %if (%sysfunc(countw(&by.)) eq 2 and &sortorder. eq 2 ) %then
%do;
totaln = sum(&sumvar.);
%end;
%else %if %sysfunc(countw(&by.)) eq 1 %then
%do;
if statistic ne "&displaytext." then totaln = sum(&sumvar.);
else totaln = .;
%end;
run;
%if %str(&by.) ne %str() %then
%do;
%if %sysfunc(countw(&by.)) eq 2 %then
%do;
%if %str(&sortorder.) eq 2 %then
%do;
/*Sorting the dataset based on descening of total and formatting if 2 by variables present*/
data __&dsin._4z;
set __&dsin._4;
by %scan(&by.,1,%str( )) notsorted;
retain checkvar;
if first.%scan(&by.,1,%str( )) then checkvar = totaln;
run;
proc sort data = __&dsin._4z out = __&dsin._4y;
by descending checkvar %scan(&by.,1,%str( )) descending totaln;
run;
%end;
data __&dsin._4(drop=%scan(&by.,1,%str( )) %scan(&by.,2,%str( )) %if &sortorder. eq 2 %then checkvar;);
length statistic $400.;
set %if &sortorder. eq 2 %then __&dsin._4y; %else __&dsin._4;;
if not missing(%scan(&by.,2,%str( ))) then statistic = cat(" ",strip(%scan(&by.,2,%str( ))));
else statistic = %scan(&by.,1,%str( ));
%do i = 1 %to %sysfunc(countw(%quote(&sumvar.)));
if statistic ne "%nrbquote(&displaytext.)" then do;
if missing(%scan(%quote(&sumvar.),&i.,%str(,))) then %scan(%quote(&sumvar.),&i.,%str(,)) = 0;
else %scan(%quote(&sumvar.),&i.,%str(,)) = %scan(%quote(&sumvar.),&i.,%str(,));
end;
%end;
totaln = sum(&sumvar.);
run;
%if %nrbquote(&displaytext.) ne %str() %then
%do;
data dummy;
statistic = "%nrbquote(&displaytext.)";
run;
data __&dsin._4;
length statistic $400.;
set dummy __&dsin._4;
run;
%end;
%end;
/*Sorting the dataset by descending of total if 1 by variable is present*/
%if %sysfunc(countw(&by.)) eq 1 and %nrbquote(&displaytext.) eq %str() %then %do;
%if &sortorder. eq 2 %then %do;
proc sort data = __&dsin._4;
by descending totaln;
run;
%end;
%end;
%end;
%if %str(&percent.) eq %str(Y) %then
%do;
/*Calculation of percentages if percent parameter is specified as Y*/
data __&dsin._5(keep=statistic col: ord);
retain statistic col1;
set __&dsin._4;
%if %str(&by.) eq %str() %then
%do;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
label col&i. = "%scan(&headvarlb.,&i.,%str(**)) N=(%cmpres(&&div&i.))";
%if &&div&i. ne 0 %then %do;
col&i. = ifc(&&divname&i. in (0,100),cats(&&divname&i.),cat(cats(&&divname&i.),
" (",strip(put((&&divname&i./&&div&i.)*100,5.1)),"%)"));
%end;
%else %do; col&i. = "0"; %end;
%end;
total = ifc(totaln in (0,100),cats(totaln),cat(cats(totaln)," (",strip(put((totaln/&tot.)*100,5.1)),"%)"));
%end;
%else
%do;
%if %nrbquote(&displaytext.) ne %str() %then %do;
/*Assigning the variable label of final dataset with treatment description and counts*/
if statistic ne "%nrbquote(&displaytext.)" then
do;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
label col&i. = "%scan(&headvarlb.,&i.,%str(**)) N=(%cmpres(&&div&i.))";
%if &&div&i. ne 0 %then %do;
col&i. = ifc(&&divname&i. in (0,100),cats(&&divname&i.),cat(cats(&&divname&i.),
" (",strip(put((&&divname&i./&&div&i.)*100,5.1)),"%)"));
%end;
%else %do; col&i. = "0"; %end;
%end;
total = ifc(totaln in (0,100),cats(totaln),cat(cats(totaln)," (",strip(put((totaln/&tot.)*100,5.1)),"%)"));
end;
%end;
%else %do;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
label col&i. = "%scan(&headvarlb.,&i.,%str(**)) N=(%cmpres(&&div&i.))";
%if &&div&i. ne 0 %then %do;
col&i. = ifc(&&divname&i. in (0,100),cats(&&divname&i.),cat(cats(&&divname&i.),
" (",strip(put((&&divname&i./&&div&i.)*100,5.1)),"%)"));
%end;
%else %do; col&i. = "0"; %end;
%end;
total = ifc(totaln in (0,100),cats(totaln),cat(cats(totaln)," (",strip(put((totaln/&tot.)*100,5.1)),"%)"));
%end;
%end;
label col%eval(%sysfunc(countw(&headvar.,%str(**)))+1) = "Total (N=%cmpres(&tot.))";
col%eval(%sysfunc(countw(&headvar.,%str(**)))+1) = total;
ord = &ord.;
run;
%end;
/*If no percentage is requested, only count is calculated*/
%else
%do;
data __&dsin._5(keep=statistic col: ord);
retain statistic col1;
set __&dsin._4;
%do i = 1 %to %sysfunc(countw(&headvar.,%str(**)));
label col&i. = "%scan(&headvarlb.,&i.,%str(**)) N=(%cmpres(&&div&i.))";
col&i. = ifc(not missing(&&divname&i.),cats(&&divname&i.),"");
%end;
total = ifc(not missing(totaln),cats(totaln),"");
label col%eval(%sysfunc(countw(&headvar.,%str(**)))+1) = "Total (N=%cmpres(&tot.))";
col%eval(%sysfunc(countw(&headvar.,%str(**)))+1) = total;
ord = &ord.;
run;
%end;
%let datct = &syslast.;
/*Appending the finaltable to existing datasets*/
%if %str(&append.) eq %str(Y) %then
%do;
%if %sysfunc(exist(finaltable)) eq 0 %then
%do;
%put %str(WAR)NING: Append parameter is given as Y but the dataset finaltable does not exist.;
%abort;
%end;
data finaltable;
length statistic $400.;
set finaltable &datct.;
run;
%end;
%else %if %str(&append.) eq %str(YS) %then
%do;
%if %sysfunc(exist(finaltable)) eq 0 %then
%do;
%put %str(WAR)NING: Append parameter is given as Y but the dataset finaltable does not exist.;
%abort;
%end;
data dummy;
statistic = "";
run;
data finaltable;
length statistic $400.;
set finaltable dummy &datct.;
run;
%end;
%else
%do;
data finaltable;
set &datct.;
run;
%end;
/*Deleting intermediate datasets in work library*/
proc datasets library = work;
delete __&dsin.1: __&dsin._: dummy: &table._: fmtt: ;
quit;
ods select all;
%mend summary;