The overal goal is to stratify quantitative variables based on their percentile. I would like to break it up into 10 levels (e.g. 10th, 20th, ...100th percentile)
The following should work for you dynamically with no hard-coding -- I edited to compact it into a single macro. Essentially it puts your desired variables into a list, creates a dataset using your output, and then uses the variable contents to put your data steps into long strings. These strings are then put into a macro variable and you can call it in your final data step. Again, no hard-coding involved.
%MACRO stratify(library=,input=,output=);
%local varlist varlist_space data_step_list;
** get vars into comma-separated list and space-separated list **;
proc sql noprint;
select NAME
into: varlist separated by ","
from dictionary.columns
where libname=upcase("&library.") and memname=upcase("&input.");
select NAME
into: varlist_space separated by " "
from dictionary.columns
where libname=upcase("&library.") and memname=upcase("&input.");
quit;
%percentiles(%bquote(&varlist.));
** put data into long format **;
proc transpose data = pcts out=pcts_long;
by recode percentile;
var &varlist_space.;
run;
** sort to get if-else order **;
proc sort data = pcts_long;
by _NAME_ percentile;
run;
** create your if-then strings using data itself **;
data str;
length STR $100;
set pcts_long;
bin = percentile/10;
by _NAME_;
if first._NAME_ then do;
STR = "if "||strip(_NAME_)||" <= "||strip(put(COL1,best.))||" then "||catx("_","recode",_NAME_)||" = "||strip(put(bin,best.))||";";
end;
else do;
STR = "else if "||strip(_NAME_)||" <= "||strip(put(COL1,best.))||" then "||catx("_","recode",_NAME_)||" = "||strip(put(bin,best.))||";";
end;
run;
** put strings into a list **;
proc sql noprint;
select STR
into: data_step_list separated by " "
from STR;
quit;
** call data step list in final data **;
data &output.; set &input.;
&data_step_list.;
run;
proc print data = &output.(obs=5);
run;
%MEND;
%stratify(library=work,input=test,output=final);