Macro - Conditional Iteration

Reply
Occasional Contributor
Posts: 16

Macro - Conditional Iteration

Hello friends,

 

I work at a university which adds a '1', '3', or '6' to the end of a year to designate which semester we're currently in, where 1 = spring, 3 = summer, and 6 = fall. So term = 20146 would mean term = fall semester year 2014. We have a macro which builds large datasets, based on an observation's "term" value, for fall and spring semesters, only. I would like to modify the macro to also include summer terms. Here is the original macro:

 

%macro build_datasets (start, stop, skip, oirdir, oirprefix, dsn);
proc datasets library=work; delete &dsn; run; %do i=&start %to &stop %by &skip; data temp; set &oirdir..&oirprefix.&i.; run; proc append base=&dsn data=temp force; run; %end; run; %mend build_datasets;
%build_datasets(20136, 20156, 5, studb, bot, students);

After running the %build_datasets function, a dataset containing five of our datasets from the "studb" library - bot20136, bot20141, bot20146, bot20151, bot20156 - is built. 

 

What I really need is a macro which would produce two additional datasets, for the summer terms, such that seven datasets would be produced: bot20136, bot20141, bot20143, bot20146, bot20151, bot20153, bot20156. 

 

In order to achieve this, I'd like to modify the previous maco as little as possible, because we have many dozens of programs in which this macro will need to be tweaked. Importantly, the modification needs to make it possible to include OR exclude summer terms.

 

I've attempted to modify this for the last four hours, without success - just error after error after error. Can anybody recommend an effecient solution? Thanks so much for ANY help you can offer!

Super User
Posts: 6,939

Re: Macro - Conditional Iteration

To concatenate datasets, all you need is a simple data step and a list of the datasets in the set .... ; statement.

So I would do the logic of building a list of datasets in a separate data step and save the list of datasets in a macro variable with call symput.

The data step provides more flexibility and is easier to debug.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Super User
Posts: 5,083

Re: Macro - Conditional Iteration

You may find this helpful:

 

http://blogs.sas.com/content/publishing/2015/01/30/sas-authors-tip-getting-the-macro-language-to-per...

 

Also note, you mention you are dealing with "large" data sets.  If you build inefficient code, it will still be inefficient if you design a macro to execute it.  In this case, you could cut your processing in half.  All that is required inside the %DO loop is:

 

proc append base=&dsn data=&oirdir..&oirprefix.&i. force; run;

 

There is no need to create a data set TEMP along the way.  Good luck.

 

 

Contributor ndp
Contributor
Posts: 61

Re: Macro - Conditional Iteration

you can simply create a list of datasets between start and stop values into a macro variable (using proc sql and into: statement) and set them together in one step instead of doing this itteratively. Let us know if you need help with the code.

Super User
Posts: 17,837

Re: Macro - Conditional Iteration

I would do it this way:

 

1. Extract list of datasets from SASHELP.VTABLE that fall between start and end date

2. Determine if summer is applicable or not

3. Generate list of datasets into a macro variable

4. Use a data step to SET all or a proc append loop

 

Frequent Contributor
Posts: 130

Re: Macro - Conditional Iteration

[ Edited ]

I modified your macro to include an extra paramter called summer.  If the value of that parameter is equal to Y, the macro will then run the append procedure from your start to your stop variable by the skip increment (which will need to be set equal to 2).  When the semester notation is equal to 5, the macro will recreate the variable and set the semester notation equal to 6.  When the semester notation is equal to 8, the macro will recreate the variable and add 1 to the year and set the semester notation equal to 1.  That way you will have it loop through from start to stop with the values of the semester notation only able to be equal to 1, 3, or 6.  If the value of the new parameter is equal to N, then the skip increment will need to be set equal to 5 and it will run the same way it did previously.

 

I also modified the macro to remove the data step where it's creating the data set temp, as this is unnecessary and time consuming to have as it reads each row of the studb.botyyyys data sets.  Instead, it will take the studb.botyyyys data set and append it directly to the base data set students.  Hope this helps you out!

 

%macro build_datasets (start, stop, skip, summer, oirdir, oirprefix, dsn);
proc datasets library=work; delete &dsn; run;
/*** If summer parameter equals Y ***/
%if &summer=Y %then %do;
	/*** Loop from start to stop by skip (which should equal 2) ***/
	%do i=&start %to &stop %by &skip;
		/*** If semester value equals 5, change to 6 ***/
		%if %substr(&i,%length(&i),1)=5 %then %do;
			%let year=%substr(&i,1,4);
			%let i=&year6;
		%end;
		/*** If semester value equals 8, move year ahead by 1 and change to 1 ***/
		%else %if %substr(&i,%length(&i),1)=8 %then %do;
			%let year=%substr(&i,1,4);
			%let yearn=%sysevalf(%sysfunc(inputn(&year,best4.))+1);
			%let i=&yearn1;
		%end;
		/*** If semester value equals 1, 3, or 6 do nothing ***/
		%else %do;
		%end;
		/*** Append year/semester data to base ***/
		proc append base=&dsn data=&oirdir..&oirprefix.&i. force; run;
	%end;
%end;

/*** If summer parameter equals N ***/
%else %do;
	/*** Loop from start to stop by skip (which should equal 5) ***/
	%do i=&start %to &stop %by &skip;
		/*** Append year/semester data to base ***/
		proc append base=&dsn data=&oirdir..&oirprefix.&i. force; run;
	%end;
%end;
%mend build_datasets;

/*** If summer = Y Then skip = 2 ***/
%build_datasets(20136, 20156, 2, Y, studb, bot, students);

/*** If summer = N Then skip = 5 ***/
%build_datasets(20136, 20156, 5, N, studb, bot, students);
Super User
Posts: 10,500

Re: Macro - Conditional Iteration

Did you try anything like:

 

data temp;
set &oirdir..&oirprefix.&start  - &oiddir..&oirprefix.&stop;
run;

PROC Star
Posts: 1,562

Re: Macro - Conditional Iteration

[ Edited ]

Unfortunately I had to modify your macro a bit. It is just too inefficient to append large tables over and over again.

Better to read once and write once and be done. Even better, maybe a view would be enough to suit your needs.

Just pick any term(s) you want when you run the macro.

 

data  BOT20136
      BOT20141
      BOT20143
      BOT20146
      BOT20151
      BOT20153 
      BOT20156;
  X=1;
run;

%macro build_datasets (start, stop, terms , oirdir, oirprefix, dsn);
  %local year term;
  %let year=%substr(&start,1,4);
  %let term=%substr(&start,5,1);  
	data &dsn.;
	  set  
    %do %until(&year.&term. > &stop.);
      %if %index(&terms, &term) %then   &oirdir..&oirprefix.&year.&term. ;
      %if       &term=1 %then      %let term=3;
      %else %if &term=3 %then      %let term=6;
      %else %if &term=6 %then %do; %let term=1; %let year=%eval(&year+1); %end;
    %end;
 		;
	run;
%mend build_datasets;           
%build_datasets(20136, 20156, 1 3 6 , WORK, BOT, STUDENTS);

 

 

More performance tips at http://www.amazon.com/High-Performance-SAS-Coding-Christian-Graffeuille/dp/1512397490

Ask a Question
Discussion stats
  • 7 replies
  • 468 views
  • 2 likes
  • 8 in conversation