DATA Step, Macro, Functions and more

Skip few iterations when condition met

Accepted Solution Solved
Reply
Super Contributor
Posts: 503
Accepted Solution

Skip few iterations when condition met

[ Edited ]

Hi Everyone,

I run 2 do-loop (DO a and DO h). In the inner loop, when the record of the output file is equal to a number, say 0, I want to skip 2 h (2 steps in inner loop).

In this example, for age=12 and Height=50, there is 0 record, so the next iteration will be age=12 and height = 57 (new h = 1+2).

I guess it will be something like 

		%if &N_record=0 %then goto "THIS PLACE";

	%end;
		"THIS PLACE" &h=&h+2;
	%end;

Thank you so much for your help.

 

HHCFX

 

data have; set sashelp.class; run;

%Macro skip;
	%let age_list	 = 12 13 ;
	%let Height_list = 50 55 56 57 58;

	%do a=1 	%to %sysfunc(countw(&age_list));
	%do H=1 	%to %sysfunc(countw(&Height_list));

		data Age&a._Height&H ; set have;
		if age=(value of age associated with &a) and height>(value of Height associated with &h);run;

		proc sql noprint; select count(*) into:N_record from Age&a._Height&H;quit;

		%if &N_record=0 %then new h =&h+2;

	%end;
	%end;
%Mend;

%SKIP;

 

 

 KEY


data have; set sashelp.class; run;

options mlogic symbolgen ;

%Macro skip;
	%let age_list	 = 12 13 ;
	%let Height_list = 50 55 56 57 58;

	%do a=1 	%to %sysfunc(countw(&age_list));
	%do H=1 	%to %sysfunc(countw(&Height_list));

		%put &h;
		data Age&a._Height&H ; set have;
		if age=%scan(&age_list, &a) and height<%scan(&height_list, &h);run;

		proc sql noprint; select count(*) into:N_record from Age&a._Height&H;quit;

		%if &n_record = 0 %then %let h = %eval(&h + 2) ; /*This new h will go to the next step at the %end to make it h+1--> +2 become +2+1= +3;  */

	%end;
	%end;
%Mend;

%SKIP;

options nosymbolgen nomlogic;

 


Accepted Solutions
Solution
‎02-12-2018 11:31 AM
Super User
Posts: 6,637

Re: Skip few iterations when condition met

Hmmmm ....

 

The code looks OK.  Here's what I would try.

 

Replace the line that skips:

 

%if &n_record = 0 %then %let h = %eval(&h + 2) ;

 

And before running, add this line:

 

options mlogic symbolgen;

 

That will force the macro processor to tell us what it is looking at, as it interprets the program.

View solution in original post


All Replies
Super User
Posts: 6,637

Re: Skip few iterations when condition met

You're present statement is very close.  It can stay in the same location, but switch to:

 

%if &n_record=0 %then %let h = &h + 2;

 

You still have a gap in the logic ... how do you retrieve "value of age associated with &a" ?

 

That would be:

 

%scan(&age_list, &a)

 

Similarly for the height list:

 

%scan(&height_list, &h)

Super Contributor
Posts: 503

Re: Skip few iterations when condition met

Posted in reply to Astounding

Since I have big marco, so I try to optimize the process using this method.

By the way, I use your code, SAS run the first iteration and error notice show up, I guess when it check the %IF condition.

 

 

data have; set sashelp.class; run;

%Macro skip;
	%let age_list	 = 12 13 ;
	%let Height_list = 50 55 56 57 58;

	%do a=1 	%to %sysfunc(countw(&age_list));
	%do H=1 	%to %sysfunc(countw(&Height_list));

		%put &h;

		data Age&a._Height&H ; set have;
		if age=%scan(&age_list, &a) and height<%scan(&height_list, &h);run;

		proc sql noprint; select count(*) into:N_record from Age&a._Height&H;quit;

		%if &N_record=0 %then %let h =&h+2;

	%end;
	%end;
%Mend;

%SKIP;

18487228 %Mend;
18487229
18487230 %SKIP;
1

NOTE: There were 19 observations read from the data set WORK.HAVE.
NOTE: The data set WORK.AGE1_HEIGHT1 has 0 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds


NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds


ERROR: The index variable in the %DO H loop has taken on an invalid or missing value. The
macro will stop executing.
ERROR: The macro SKIP will stop executing.

Solution
‎02-12-2018 11:31 AM
Super User
Posts: 6,637

Re: Skip few iterations when condition met

Hmmmm ....

 

The code looks OK.  Here's what I would try.

 

Replace the line that skips:

 

%if &n_record = 0 %then %let h = %eval(&h + 2) ;

 

And before running, add this line:

 

options mlogic symbolgen;

 

That will force the macro processor to tell us what it is looking at, as it interprets the program.

Super Contributor
Posts: 503

Re: Skip few iterations when condition met

Posted in reply to Astounding

SAS now runs but it skip from 1 to 4 instead of 1 to 3.

Also an error on the option show up.

By the way, how to turn this option off so Log file come back to normal?


Thanks a lot.

 

18487399 options mlogic symbolgen noprint;
11: LINE and COLUMN cannot be determined.

 

SYMBOLGEN: Macro variable H resolves to 1
1
SYMBOLGEN: Macro variable A resolves to 1
SYMBOLGEN: Macro variable H resolves to 1
SYMBOLGEN: Macro variable AGE_LIST resolves to 12 13
SYMBOLGEN: Macro variable A resolves to 1
SYMBOLGEN: Macro variable HEIGHT_LIST resolves to 50 55 56 57 58
SYMBOLGEN: Macro variable H resolves to 1

 

SYMBOLGEN: Macro variable N_RECORD resolves to 0
MLOGIC(SKIP): %IF condition &n_record = 0 is TRUE
MLOGIC(SKIP): %LET (variable name is H)
SYMBOLGEN: Macro variable H resolves to 1
MLOGIC(SKIP): %DO loop index variable H is now 4; loop will iterate again.
MLOGIC(SKIP): %PUT &h
SYMBOLGEN: Macro variable H resolves to 4
4

 

Super Contributor
Posts: 331

Re: Skip few iterations when condition met

Hello,

 

H should only be increased by 1 since a new increment is added by the loop.

Try %let h=%eval(&h.+1);

Super Contributor
Posts: 331

Re: Skip few iterations when condition met

And option nomprint
Super Contributor
Posts: 503

Re: Skip few iterations when condition met

Thanks a lot.

 

In the future, where should I post that kind of Macro question or I can post here in the "Base SAS Programming".

 

HHCFX

Super User
Posts: 6,637

Re: Skip few iterations when condition met

Yes, skipped from 1 to 4 because you asked for that in describing the problem ... skip from 50 to 57.  As @gamotte recommended, switch to:

 

... %let h = %eval(&h + 1);

 

Also, you can remove the options statement since the error is gone.  If you are using a continuous session (such as Enterprise Guide), you can re-set them with:

 

options nosymbolgen nomlogic;

Super Contributor
Posts: 503

Re: Skip few iterations when condition met

Posted in reply to Astounding

You are right. Now I understand the process.

 

In the future, where should I post that kind of Macro question or I can post here in the "Base SAS Programming".

 

HHCFX

Super User
Posts: 6,637

Re: Skip few iterations when condition met

You posted in the right place (which is Base SAS Programming).  There is also a General SAS Programming category, but the description of Base SAS Programming specifically includes macro language.  Sometimes it's difficult to tell where to post because a problem might span more than one category.  The most important advice is to post just once, not twice.

Super User
Super User
Posts: 9,427

Re: Skip few iterations when condition met

What is it your trying to do?  It seems like every post you have made here seems to be trying to re-create base SAS in macro language.  Why not simplfy your life and use Base SAS, why continue to fight the system?  from the code below, you simply want to create a set of counts based on a categorisation.  Categorise your data in one datastep, e.g.

data inter;
  set have;
  if age=12 and 50 <= height < 58 then cat="Cat1";
  ...;
run;

proc means data=inter;
  var cat1;
  output out=want;
run;

Macro is not a replacement for base SAS!!

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 11 replies
  • 254 views
  • 3 likes
  • 4 in conversation