Question

I have a lot of sas dataset files that starts with "s" followed by some numbers like s1 s7 s13 s32 etc. (I have a lot). For each files I run a set of codes, save my last result and then restart with with the following dataset file. Normally, when my dataset file numbers are sequential like s1 s2 s3 s4 s5...it is easy to use for instance a %do i=1 %to 120. But what if I want to do a loop with unequal increments? How can I do this? Like for instance a %do i=1 7 13 32.... This is quite easy in MATLAB but in SAS I am not too sure how.

Was it helpful?

Solution

%SCAN is your friend here. Take a look at the example code below -

%let nums = 1 2 4 6 13 29 32;

%macro iter();

%let cnt = %sysfunc(countc(&nums," "));
%let cnt = %eval(&cnt + 1);
%put &cnt;

%do i = 1 %to &cnt;
%put I will now process dataset s%scan(&nums,&i," ");
%end;

%mend iter;

%iter()

You can modify the part %put... to write a DATA step.

OTHER TIPS

Make your %do from the lowest data set number to highest. Then just check to see if the data set exists.

%Let lib=yourlib;
%Macro Process;

 %Do i = 1 %to 1000;
  %if %sysfunc(exist(&lib..s&i)) %then %do;

    <your code>

  %end;

 %end;

%Mend process;
%process

The example below takes data sets S1, S3 and S10 and processes them, outputting data sets NEW1, NEW3 and NEW10:

/* Example data sets */
data s1 s3 s10;
run;

%macro mymac;

  /* Create 'array' of macro variables DSET1, DSET2...up to a max of DSET9999.
     Each DSETx macro variable will contain a data set number. */
  proc sql noprint;
    select compress(memname,"sS") into :dset1-:dset9999
    from sashelp.vtable
    where libname="WORK" and upcase(substr(memname,1,1))="S"
          and input(compress(memname,"sS"),8.) ne .;
  quit;
  %let numdsets=&sqlobs;

  /* Process data sets */    
  %do i=1 %to &numdsets.;
    data new&&dset&i.;
      set s&&dset&i.;
    run;
  %end;
%mend mymac;
%mymac

You can do non-sequential increments in a normal do loop, but not in a macro do loop the same way. There is a workaround on the SAShelp website.

http://support.sas.com/kb/26/155.html

I would first put the numbers in a comma separated macro list using the following code. The prxmatch function searches for dataset names that begin with an 'S', followed by a digit(s). Once you have this, you can follow the code on the SAS website.

proc sql noprint;
select compress(upper(memname),'S') into :ds_num separated by ',' from dictionary.tables
where libname='WORK' and prxmatch("/S\d+/",upper(memname));
quit;

%put &ds_num.;

This is an update for Mozan's answer above. I do not recommend using CountC to count the elements in a list. Use CountW instead. Note update below:

%let nums = 1 2 4 6 13 29 32;

%macro iter();

%let cnt = %sysfunc(CountW(&nums));
%put &cnt;

%do i = 1 %to &cnt;
  %put I will now process dataset s%scan(&nums,&i);
%end;

%mend iter;

%iter()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top