DATA Step, Macro, Functions and more

Updating

Accepted Solution Solved
Reply
Contributor
Posts: 47
Accepted Solution

Updating

Hey all,

Does someone see why my values don't update by each iteration i ?
I want values update in each iteration i and throughout my statements.

 

data need;
	do i= 1 to 5;
		min= 1; max= 10; val_m1= 5; val_m2= 7;
		m1= 3;
		m2= 5;
		min= m1; m1= m2;	 		            /*here 2 updates*/
 		val_m1= val_m2;  		                    /*update*/
		m2= (m2 + max) / 2; 		            /*update*/
		call execute('%mymacro('||m2||')'); 
 /*These macro have to use the last m2 update value */
		val_m2= &val_m2; 	
 /*A global macro var named val_m2 is created in %mymacro*/
	
       output;
       end;
run;

 

Mymacro like this one:

 

%macro mymacro (m2);
   %glabal val_m2;                      /*name can be changed if optimal*/
   ...
   ...
%mend;

 

Best Regards


Accepted Solutions
Solution
‎07-10-2017 07:56 AM
Super User
Posts: 5,071

Re: Updating

Kurt mentioned the right principle ... there is absolutely nothing about your code that changes &USED within this statement:

 

val2 = &used;

 

Its value gets changed by this code, but the statements within the DATA step depend on the initial value of &USED before the DATA step begins.  You could work around this by replacing that statement with:

 

val2 = input(symget('used'), 12.);

 

It's untested but worth a try with one just one precaution.  I hope this is just a test to see how macro language works.  If this were a real application, there would likely be many better ways to handle the situation.

View solution in original post


All Replies
Super User
Posts: 6,928

Re: Updating

In this line

val_m2= &val_m2;

the macro variable &val_m2 is resolved by the macro PREprocessor before the data step is compiled and run.

 

I strongly suggest that you pack the logic contained in the macro in a user defined function, or rewrite the macro so that you can use it to create standard code for use in the data step itself (without call execute).

 

For further help, post the code of your macro %mymacro.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Contributor
Posts: 47

Re: Updating

" the macro variable &val_m2 is resolved by the macro PREprocessor before the data step is compiled and run "

 

You 're right, thanks.

 

But i reformulated the problem for simplicity.

%macro mymacro(var);
%Global used;
	%let used= %sysevalf(&var +1);
%Mend;

data need;
do i= 1 to 3;
	if i= 1 then do;
		x= 2;
		y= 3;
		call execute('%mymacro('||x||')');
		val2= &used;           
	end;
	else do;
		x= x+2;
		y= (y+2)/2;
		call execute('%mymacro('||x||')');
		val2= &used;
	end;
output;
end;
run;

 

 

Data want:

 

 i     x    y         val2

1    2    3          3
2    4    2.5       5
3    6    2.25     7
Solution
‎07-10-2017 07:56 AM
Super User
Posts: 5,071

Re: Updating

Kurt mentioned the right principle ... there is absolutely nothing about your code that changes &USED within this statement:

 

val2 = &used;

 

Its value gets changed by this code, but the statements within the DATA step depend on the initial value of &USED before the DATA step begins.  You could work around this by replacing that statement with:

 

val2 = input(symget('used'), 12.);

 

It's untested but worth a try with one just one precaution.  I hope this is just a test to see how macro language works.  If this were a real application, there would likely be many better ways to handle the situation.

Super User
Posts: 6,928

Re: Updating

Still the same mistake. &used will be resolved BEFORE!! the macro calls from the call execute will create the macro variable.

If you just want to build an increment, macro programming is NOT NEEDED AT ALL.

 

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Contributor
Posts: 47

Re: Updating

i knew very well that the macro reference were resolved first. 

Thanks so much to all !

 

Regards  

Contributor
Posts: 47

Re: Updating

What about te informat 12. applied to the numeric variable val2 ?

Could the number of digit in my global macro var used be an issue ?

Such it doesn't work with my initial data.

 

Regards

Contributor
Posts: 47

Re: Updating

For example this one fails do execute:

:

data need4;
do i= 1 to 3;
	if i= 1 then do;
		x= 22222222222;
		y= 33333333333;
		val_x= 11111111111;
		call execute('%mymacro('||x||')');
		val_y = input(symget('used'), 12.); 
	end;
	else do;
		x= x+2;
		y= (y+2)/2;
		val_x= val_y; 
		call execute('%mymacro('||x||')');
		val_y = input(symget('used'), 12.);
	end;
output;
end;
run;

run;
Super User
Posts: 5,071

Re: Updating

When I run your code, it works.  What failed to execute?

 

Yes, the informat could be a problem.  But not for 11-digit integers.  There might be an issue with different formulas if they generate decimal fractions.  But the code that you posted should run without incident.

Contributor
Posts: 47

Re: Updating

True. It may be because of my own operations.
Also, in my elso do: call execute don't use my last x value. Any thoughts ?

 

Regards

Super User
Posts: 5,071

Re: Updating

[ Edited ]

Here are the results I got:

 

Obs i  x            y             val_x          val_y

 

1   1  22222222222 33333333333.0 11111111111 22222222223

2   2  22222222224 16666666667.5 22222222223 22222222225

3   3  22222222226 8333333334.8  22222222225 22222222227

 

Did you get the same?  The results are short enough that you should be able to post them and explain how they are different than what you expect.

 

 

 

Contributor
Posts: 47

Re: Updating

True. My problem is from my original own macro i think.

Regards

☑ This topic is SOLVED.

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

Discussion stats
  • 11 replies
  • 158 views
  • 5 likes
  • 3 in conversation