I'm running SAS 9.4 TS Level 1M3.
I have a macro called FILTER_DATA. I use it to create smaller data sets by filtering SASHELP.CLASS.
%macro filter_data(sex, index, age1, age2, age3); data class_&sex._&index; set sashelp.class;
if sex = "&sex"; if age = &age1 or age= &age2 or age = &age3; run; %mend;
My challenge is to loop through many applications of FILTER_DATA. Instead of explaining how I want to loop them, it's easier just to show you.
%FILTER_DATA(M, 1, 11, 12, 13);
%FILTER_DATA(M, 2, 12, 13, 14);
%FILTER_DATA(M, 3, 13, 14, 15);
%FILTER_DATA(F, 1, 11, 12, 13);
%FILTER_DATA(F, 2, 12, 13, 14);
%FILTER_DATA(F, 3, 13, 14, 15);
What code can implement all 6 lines in a loop?
You can do what you want like this:
%macro runit;
%local sexes index i j sex;
%let sexes=MF;
%do index=1 %to 3;
%do i=1 %to 2;
%let sex=%substr(&sexes,&i,1);
%filter_data(&sex,&index,%eval(&index+10),%eval(&index+11),%eval(&index+12));
%end;
%end;
%mend;
%runit;
But you will get more mileage with large data if you use the conditions to split the data in one datastep, e.g.:
%macro split_data(sexes,indexes);
%local i j;
data
%do i=1 %to %sysfunc(countw(&sexes));
%do j=1 %to %sysfunc(countw(&indexes));
%let sex=%scan(&sexes,&i);
%let index=%scan(&indexes,&j);
class_&sex._&index
%end;
%end;
;
set sashelp.class;
%do i=1 %to %sysfunc(countw(&sexes));
%do j=1 %to %sysfunc(countw(&indexes));
%let sex=%scan(&sexes,&i);
%let index=%scan(&indexes,&j);
if sex="&sex" and age in(%eval(&index+10),%eval(&index+11),%eval(&index+12)) then
output class_&sex._&index;
%end;
%end;
run;
%mend;
%split_data(M F,1 2 3);
CALL EXECUTE. Check Example 2 the documentation for the example.
Create a data step loop and pass the arguments to the macro that way. A data step loop is easier to manage.
Create a dataset with your filter value combinations and use call execute from that to execute your macro repeatedly.
You can do what you want like this:
%macro runit;
%local sexes index i j sex;
%let sexes=MF;
%do index=1 %to 3;
%do i=1 %to 2;
%let sex=%substr(&sexes,&i,1);
%filter_data(&sex,&index,%eval(&index+10),%eval(&index+11),%eval(&index+12));
%end;
%end;
%mend;
%runit;
But you will get more mileage with large data if you use the conditions to split the data in one datastep, e.g.:
%macro split_data(sexes,indexes);
%local i j;
data
%do i=1 %to %sysfunc(countw(&sexes));
%do j=1 %to %sysfunc(countw(&indexes));
%let sex=%scan(&sexes,&i);
%let index=%scan(&indexes,&j);
class_&sex._&index
%end;
%end;
;
set sashelp.class;
%do i=1 %to %sysfunc(countw(&sexes));
%do j=1 %to %sysfunc(countw(&indexes));
%let sex=%scan(&sexes,&i);
%let index=%scan(&indexes,&j);
if sex="&sex" and age in(%eval(&index+10),%eval(&index+11),%eval(&index+12)) then
output class_&sex._&index;
%end;
%end;
run;
%mend;
%split_data(M F,1 2 3);
Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.
Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.
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.