BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
rj_missionbeach
Fluorite | Level 6

I have a large number of loops to run and want to save the data every 1000 loops or so.

In the code below, rather than saying %if &v.=5 or &v.=10 or &v=15 or &v.=20, I'd like to say if &v is a multiple of 5. Any suggestions would be greatly appreciated

data a1; input id $ count ; 
datalines;
A	1	
A	2	
A	3	
A	4	
A	5	
A	6	
A	7	
A	8	
A	9	
A	10	
A	11	
A	12	
A	13	
A	14	
A	15	
A	16	
A	17	
A	18	
A	19	
A	20	
;

proc datasets; delete bb;

libname saveme 'f:\temp\saveme';

%macro loop;
	%do v=1 %to 20;
		
		data b; set a1; if count=&v.;
		count_sq=count**2;

		proc append base=bb data=b;

		%if &v.=5 or &v.=10 or &v.=15 or &v.=20 %then %do;
			%let x=%eval(&v./5);
				data saveme.eth_&x.; set bb;
				proc datasets; delete bb;
		%end;
	%end;
%mend loop;
%loop;
run;
1 ACCEPTED SOLUTION

Accepted Solutions
whymath
Lapis Lazuli | Level 10

Since you ask for selecting every fifth loop: 5, 10, 15, 20, ... The last digit is always 0 or 5, it is a very simple mathematical phenomenon.

So you can validate if the last number of &v. in (0 5) or not.

%macro loop/minoperator;
	%do v=1 %to 20;
		
		data b; set a1; if count=&v.;
		count_sq=count**2;

		proc append base=bb data=b;

		%if %substr(&v.,%length(&v.)) in (0 5) %then %do;
			%let x=%eval(&v./5);
				data saveme.eth_&x.; set bb;
				proc datasets; delete bb;
		%end;
	%end;
%mend loop;

Note: To use in operator in macro, you need to add "minoperator" behind you macro definition statement.

View solution in original post

6 REPLIES 6
AlanC
Barite | Level 11
I am on a cellphone and dont have SAS. The way this is done crosses pgm languages. Use the modulus of 5. For SAS, that is the mod function. Mod(counter, 5) = 0.
https://github.com/savian-net
Astounding
PROC Star

Take advantage of the fact that macro language performs integer arithmatic, dropping any remainders.  Try:

 

%if &v = &v / 5 * 5 %then %do;
whymath
Lapis Lazuli | Level 10

Since you ask for selecting every fifth loop: 5, 10, 15, 20, ... The last digit is always 0 or 5, it is a very simple mathematical phenomenon.

So you can validate if the last number of &v. in (0 5) or not.

%macro loop/minoperator;
	%do v=1 %to 20;
		
		data b; set a1; if count=&v.;
		count_sq=count**2;

		proc append base=bb data=b;

		%if %substr(&v.,%length(&v.)) in (0 5) %then %do;
			%let x=%eval(&v./5);
				data saveme.eth_&x.; set bb;
				proc datasets; delete bb;
		%end;
	%end;
%mend loop;

Note: To use in operator in macro, you need to add "minoperator" behind you macro definition statement.

ballardw
Super User

An option that is very useful is the MINOPERATOR, which allows use of the IN comparison, especially when the case might not involve wanting a choice that can be easily derived with numeric manipulation. The option on the macro of MINOPERATOR means the operator is available. If you want to use something other than the default blank for the separator between values you use the MINDELIMITER option.

%macro loop / minoperator;
	%do v=1 %to 20;
		
		data b; set a1; if count=&v.;
		count_sq=count**2;

		proc append base=bb data=b;

		%if &v. in (5 10 15 20) %then %do;
			%let x=%eval(&v./5);
				data saveme.eth_&x.; set bb;
				proc datasets; delete bb;
		%end;
	%end;
%mend loop;

STRONG suggestion for future questions: Do not include custom library assignments or use those libraries in the body of the code. We very likely do not have your drives/paths or even same operating systems. Just include the pieces that you really need to demonstrate the issue.

Second suggestion: In macro code always explicitly provide run; and/or quit; (datasets) to terminate the procedures inside the body of a macro. You never know exactly what the code following a given macro might be and leaving procedures like Datasets still running may cause some very interesting debugging situations. Your current macro leaves datasets running.

vijaypratap0195
Obsidian | Level 7

Use modulus function, which returns the remainder.

 

E.g.

when we divide 5 by 5 we get remainder 0. So Mod(5,5)=0 is True.

when we divide 10 by 5 we get remainder 0. So Mod(10,5)=0 is True.

but when we divide 11 by 5 we get remainder 1. So Mod(11,5)=0 is False.

 

Mod(&v.,5)=0

 

Hope this will resolve your issues.

 

-Vijay

rj_missionbeach
Fluorite | Level 6

Thanks all - very helpful. Was not aware of the minoperator.

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

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
  • 6 replies
  • 749 views
  • 6 likes
  • 6 in conversation