BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
hhchenfx
Barite | Level 11

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;

 

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

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

11 REPLIES 11
Astounding
PROC Star

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)

hhchenfx
Barite | Level 11

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.

Astounding
PROC Star

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.

hhchenfx
Barite | Level 11

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

 

gamotte
Rhodochrosite | Level 12

Hello,

 

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

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

gamotte
Rhodochrosite | Level 12
And option nomprint
hhchenfx
Barite | Level 11

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

Astounding
PROC Star

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;

hhchenfx
Barite | Level 11

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

Astounding
PROC Star

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.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

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!!

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

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