DATA Step, Macro, Functions and more

Using Let Statement in a Do Loop

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 7
Accepted Solution

Using Let Statement in a Do Loop

Hi All, 

Hopefully, someone can help me, I've been searching the forums all day for a solution...

I am trying to change a %LET variable within a maco's DO loop, using %eval. However i only want the %eval line to work under a certain condition, unfortunately, the %eval statement is always operating. I've tried to use %symput but I can't get that to work. 

I've pasted an extract of code below. The issues is the variable j, which is used as an index variable. Essentially i have two types variables: Building_Claim_Cause_0 and Contents_Claim_Cause_0   (both of which go up to 4, i.e Contents_Claim_Cause_1, Contents_Claim_Cause_2...)

I need to combine these two variables into one variable (HOMELOSSTx) where the buildings and contents claim variables. i.e if there is a value in Building_Claim_Cause_0, then let HOMELOSST0 equal it, and if there is a value in Contents_Claim_Cause_0  as well let HOMELOSST1 equal it. I am using j to as the index value for HOMELOSS and k as the index value between buildings and contents claims, and i as the index value between 0 to 4 for the buildings/contents claims).

 

 

 

%MACRO CLAIMS(MAXNUM);
	/*INTIALISE CLAIMS VARIABLES*/
	
	%LET i = 0;   	/*CYCLE THROUGH THE Specific_ItemX VARIABLE. IF THERE IS AN ITEM THEN SPECIFIED ITEM COVER HAS BEEN SELECTED*/
	%LET j = 0; 	/*CLAIM FOUND COUNT - WE ARE COLLAPSING THE BUILDING CLAIM VARIABLES AND CONTENTS CLAIM VARIABLES INTO ONE ONE CLAIM VARIABLE*/
	
	%DO %UNTIL (&i. = &MAXNUM.*2+2);	/*we have 5 potential bld or cnt claims. count starts at 0 hence maxnum is 4*/
		FORMAT CLAIMCOVE&i. FMT_CLAIMCOVER.;
		FORMAT HOMELOSST&i. FMT_HOMELOSSTY.;
		FORMAT HMELOSOTT&i. FMT_HMELOSOTTY.;
		FORMAT DATEOFLOS&i. DDMMYY8.;
		FORMAT PROPCLAIM&i. FMT_PROPCLAIMX.;
		FORMAT AMTPAIDOS&i 	best32.;

		CLAIMCOVE&i. = 0; 		/*Was it a contents or building incident?*/
		HOMELOSST&i. = 0; 		/*What type of incident was it?*/
		HMELOSOTT&i. = 0; 		/*Please specify:*/
		DATEOFLOS&i. = .; 		/*When did the incident occur?*/			 
		PROPCLAIM&i. = 999;	/*Did you make a claim?*/
		AMTPAIDOS&i. = .;		/*How much was paid out (or you have received so far) for this claim?*/

		%LET i = %eval(&i.+1);
	%END;
	
	%LET i = 0;/*reset counter*/
	
	%DO %UNTIL (&i. = &MAXNUM. +1);
		%LET k = 0;/*reset claim type counter (bld or cts)*/
		IF CLAIMLAST5 = 1 THEN DO;
			%DO k = 1 %TO 2;
			
				%IF &k. = 1 %THEN %DO; 
					
					%LET QZ_CLMType = 	Building_Claim_Cause_		;
					%LET QZ_CLMDate = 	Building_Claim_QuteDate_	;
					%LET QZ_CLMLoc	=	Building_Claim_Location_ 	;
					%LET QZ_CLMAmt	=	Building_Claim_Amount_ 		; 
				%END;
				%ELSE %DO;
					
					%LET QZ_CLMType = 	Contents_Claim_Cause_		;
					%LET QZ_CLMDate = 	Contents_Claim_QuteDate_	;
					%LET QZ_CLMLoc	=	Contents_Claim_Location_ 	;
					%LET QZ_CLMAmt	=	Contents_Claim_Amount_ 		;
				%END;
				
				SELECT (&QZ_CLMType.&i.);
					WHEN ("", "N") DO;
					END; /* DO NOTHING*/
					OTHERWISE DO;
						IF &k. = 1 THEN DO; 
							CLAIMCOVE&j. = 1; 		/*Was it a contents or building incident?*/
						END;
						ELSE DO;
							CLAIMCOVE&j. = 2; 		/*Was it a contents or building incident?*/
						END;
						
						SELECT (&QZ_CLMType.&i.);  
								
							WHEN ("Flood Damage") 			HOMELOSST&j. = 1; 	/*Flood*/
							OTHERWISE 						HOMELOSST&j. = 9; 												/*Other*/
						END;
						
						IF HOMELOSST&j. < 9 THEN HMELOSOTT&j. = 0;
						ELSE DO;
							SELECT (&QZ_CLMType.&i.);
								WHEN ("Additional Expenses") 	HMELOSOTT&j. = 1; 			/*Additional Expenses*/							
								OTHERWISE 						HMELOSOTT&j. = 99;
	
							END; /*HMELOSOTTY - CLAIM CAUSE CODES*/							
						END;  
						
						DATEOFLOS&j. = &QZ_CLMDate.&i.; 	/*When did the incident occur?*/			 
						SELECT (&QZ_CLMLoc.&i.);
							WHEN ("N") PROPCLAIM&j. = 3;
							WHEN ("Y") PROPCLAIM&j. = 1;
							OTHERWISE PROPCLAIM&j. 	= 99;
						END;											
						AMTPAIDOS&j. = &QZ_CLMAmt.&i.;		/*How much was paid out (or you have received so far) for this claim?*/
						%LET j = %eval(&j.+ 1);				/*This is the index value for claim variable we are using.*/
					END; /*OTHERWISE DO;*/
				END; /*SELECT (&QZ_CLMType.&i.);*/
																		
			%END; /*LOOP ACROSS Building_Claim_QuteDate_&i. and  AND Contents_Claim_Cause_&i.*/
																	
		END; /*IF CLAIMLAST5 = 1 THEN DO;*/
		%LET i = %eval(&i.+ 1);		
	%END;
%MEND; /*CLAIMS*/

data toto ;
set RAWDATA.QZDATA (KEEP = Had_Any_Building_Claims Had_Any_Contents_Claims
							Building_Claim:	Contents_Claim:
					/*OBS = 12*/);
	
/*Have you, or anyone living at your property had any incidents or made a home insurance claims in the last five years? (in this or another property)*/
	IF Had_Any_Building_Claims = "" OR Had_Any_Contents_Claims = "" THEN CLAIMLAST5 = 0;
	ELSE IF Had_Any_Building_Claims = "N" AND Had_Any_Contents_Claims = "N" THEN CLAIMLAST5 = 0;
	ELSE CLAIMLAST5 = 1;	
	
	%CLAIMS(MAXNUM = 4);  
RUN;

 


Accepted Solutions
Solution
‎07-18-2017 06:34 AM
Super User
Posts: 5,096

Re: Using Let Statement in a Do Loop

You're making a fundamental mistake in the way that you treat macro language.  Macro language does not process your data.  Instead, it is supposed to generate SAS language statements.  Those are what process your data.  To give you an example, here is a rewrite of the beginning of your code:

 

%macro claims (maxnum);

   %local j;

   %let j = %eval(2 * &maxnum + 2);

   format claimcove1 - claimcove&j fmt_claimcover.;

   format homelosst1 - homelosst&j fmt_homelossty.;

   ...

   format amtpaidos1 - amtpaidos&j  best32.;

 

   array claimcove {&j};

   array homelosst {&j};

   ...

   array propclaim {&j};

   array amtpaidos {&j};

 

   do _i_ = 1 to &j;

      claimcove{_i_} = 0;

      homelosst {_i_} = 0;

      ...

      propclaim{_i_} = 999;

   end;

 

 

You need to use macro language to generate SAS language statements, and to do that you need to have a firm idea of what the SAS statements should look like.  That part becomes a little cloudy in the second half of your macro.

View solution in original post


All Replies
Super User
Posts: 10,543

Re: Using Let Statement in a Do Loop


Squibbles wrote:

Hi All, 

 

 Essentially i have two types variables: Building_Claim_Cause_0 and Contents_Claim_Cause_0   (both of which go up to 4, i.e Contents_Claim_Cause_1, Contents_Claim_Cause_2...)

I need to combine these two variables into one variable (HOMELOSSTx) where the buildings and contents claim variables. i.e if there is a value in Building_Claim_Cause_0, then let HOMELOSST0 equal it, and if there is a value in Contents_Claim_Cause_0  as well let HOMELOSST1 equal it. I am using j to as the index value for HOMELOSS and k as the index value between buildings and contents claims, and i as the index value between 0 to 4 for the buildings/contents claims).

 


It may help to provide a little example data start and end. But it looks like a few arrays would handle this without any macro logic needed at all, at least for that look at pairs(?) of values and assign a third.

Solution
‎07-18-2017 06:34 AM
Super User
Posts: 5,096

Re: Using Let Statement in a Do Loop

You're making a fundamental mistake in the way that you treat macro language.  Macro language does not process your data.  Instead, it is supposed to generate SAS language statements.  Those are what process your data.  To give you an example, here is a rewrite of the beginning of your code:

 

%macro claims (maxnum);

   %local j;

   %let j = %eval(2 * &maxnum + 2);

   format claimcove1 - claimcove&j fmt_claimcover.;

   format homelosst1 - homelosst&j fmt_homelossty.;

   ...

   format amtpaidos1 - amtpaidos&j  best32.;

 

   array claimcove {&j};

   array homelosst {&j};

   ...

   array propclaim {&j};

   array amtpaidos {&j};

 

   do _i_ = 1 to &j;

      claimcove{_i_} = 0;

      homelosst {_i_} = 0;

      ...

      propclaim{_i_} = 999;

   end;

 

 

You need to use macro language to generate SAS language statements, and to do that you need to have a firm idea of what the SAS statements should look like.  That part becomes a little cloudy in the second half of your macro.

Occasional Contributor
Posts: 7

Re: Using Let Statement in a Do Loop

ok thanks both. 

i'll look into arrays & rethink the structure. 

☑ This topic is solved.

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

Discussion stats
  • 3 replies
  • 115 views
  • 3 likes
  • 3 in conversation