Hello,
I am working with the following six datasets:
scored_DT_list_1
scored_LR_list_1
scored_RF_list_1
scored_DT_list_2
scored_LR_list_2
scored_RF_list_2
and would like to create the next six datasets:
ranked_DT_list_1
ranked_LR_list_1
ranked_RF_list_1
ranked_DT_list_2
ranked_LR_list_2
ranked_RF_list_2
using either a loop or macro. I wanted to write an efficient, nested macro, but I am getting errors that the double ampersand macro variable (type) is not being resolved. This is the code block that is causing the error:
%macro models(type);
%macro varlist(list);
proc rank data=scored_&&type_&list out=ranked_&&type_&list groups=100 descending;
var P_Target1;
ranks CF_Score_Rank_a;
where train = 0;
run;
%mend;
%varlist(list_1);
%varlist(list_2);
%mend;
%Models(DT);
%Models(LR);
%Models(RF);
Is there a better or more efficient way to write this type of loop?
I would suggest a macro with two arguments, each of them a list. The first is a list of types, the second a list of list values, as in:
%macro doranks(types=,list=);
%do t=1 %to %sysfunc(countw(&types));
%let type=%scan(&types,&t);
%do L=1 %to %sysfunc(countw(&list));
%let listitem=%scan(&list,&L);
proc rank data=scored_&type._&listitem out=ranked_&type._&listitem groups=100 descending;
var p_target1;
ranks CF_score_rank_a;
where train=0;
run;
%end;
%end;
%mend doranks;
You can then call the "nested" loops in a single macro:
%doranks(types=DT LR RF,list=LIST_1 LIST_2);
Nesting macro definitions is typically not done. It's buggy and usually unnecessary. It seems like you're trying to go across multiple variables at once. Is this example illustrative of your real problem, or is there more lists/variables? Depending on exactly how many dimensions there are different ways to scale this.
%macro rank(type= , list=);
proc rank data=scored_&type_list_&list out=ranked_&type_list_&list groups=100 descending;
var P_Target1;
ranks CF_Score_Rank_a;
where train = 0;
run;
%mend;
Now you want to run it for three different variables and two lists (1/2), so how you generate that call can vary. If the data sets already exist, I'd run it on all data sets in the work library that had that format of a name.
data run_list;
set sashelp.vtable;
where libname = 'WORK' and memname like 'SCORED%';
type = scan(memname, 2, "_");
list = scan(memname, 4, "_");
str = catt('%rank(type=', type, ' , list=', list, ');');
call execute(str);
run;
UNTESTED.
@GuyTreepwood wrote:
Hello,
I am working with the following six datasets:
scored_DT_list_1
scored_LR_list_1
scored_RF_list_1
scored_DT_list_2
scored_LR_list_2
scored_RF_list_2
and would like to create the next six datasets:
ranked_DT_list_1
ranked_LR_list_1
ranked_RF_list_1
ranked_DT_list_2
ranked_LR_list_2
ranked_RF_list_2
using either a loop or macro. I wanted to write an efficient, nested macro, but I am getting errors that the double ampersand macro variable (type) is not being resolved. This is the code block that is causing the error:
%macro models(type);
%macro varlist(list);
proc rank data=scored_&&type_&list out=ranked_&&type_&list groups=100 descending;
var P_Target1;
ranks CF_Score_Rank_a;
where train = 0;
run;
%mend;
%varlist(list_1);
%varlist(list_2);
%mend;
%Models(DT);
%Models(LR);
%Models(RF);
Is there a better or more efficient way to write this type of loop?
I haven't tried to go thorugh your macros in detail, but if you want to take data set scored_DT_list_1 and do something to it and have an output that is named ranked_DT_list_1, then all you need to do is have a macro variable that contains the new data set name.
Something like this:
%let output_data_set_name=%sysfunc(tranwrd(&input_data_set_name,scored,ranked));
Agreeing with @Reeza , do not nest macro definitions.
I would suggest a macro with two arguments, each of them a list. The first is a list of types, the second a list of list values, as in:
%macro doranks(types=,list=);
%do t=1 %to %sysfunc(countw(&types));
%let type=%scan(&types,&t);
%do L=1 %to %sysfunc(countw(&list));
%let listitem=%scan(&list,&L);
proc rank data=scored_&type._&listitem out=ranked_&type._&listitem groups=100 descending;
var p_target1;
ranks CF_score_rank_a;
where train=0;
run;
%end;
%end;
%mend doranks;
You can then call the "nested" loops in a single macro:
%doranks(types=DT LR RF,list=LIST_1 LIST_2);
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.