SAS Programming

DATA Step, Macro, Functions and more
BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
rfrancis
Obsidian | Level 7

Hello, I'm using IML inside of a macro (found a few threads here about the topic, but nothing worked). The IML code authored by Rick Wicklin works flawlessly. I inserted this code inside of a macro, and although the macro loops, IML values are static with the first loop. Rick Wicklin addresses a very similar issue here: https://blogs.sas.com/content/iml/2013/06/19/macros-and-loops.html. The crux of the matter seems to be that the interactive nature of IML behaves quite differently than a traditional data step. I've tried, promise, but just can't get it done. I am grateful for any suggestions. Code is below.  Thank you, Rick Francis

 

 

OPTIONS SOURCE SOURCE2 MACROGEN MPRINT; %MACRO combination; data comb_1; set untrimmed (keep=group lag2cvrank lag2cfo_ts lagcfo_ts); if group=&I and lag2cvrank eq &J; *keep group lagcvrank gvkey; proc iml; *XY = {1 9, 2 15, 3 19, 4 20, 10 45, 12 55, 18 78, /* 7 data points used by Sen (1968) */ 12.5 30, 4.5 50}; /* 2 outliers (not considered by Sen) */ use work.untrimmed; read all var {lag2cfo_ts lagcfo_ts group lag2cvrank} into XY; close work.untrimmed; *XY = {lag2cfo_ts lagcfo_ts}; /* Theil uses all "N choose 2" combinations of slopes of segments. Assume that the first coordinates (X) are distinct */ c = allcomb(nrow(XY), 2); /* all "N choose 2" combinations of pairs */ group = XY[1,3]; lag2cvrank = XY[1,4]; Pt1 = XY[c[,1],]; /* extract first point of line segments */ Pt2 = XY[c[,2],]; /* extract second point of line segments */ slope = (Pt1[,2] - Pt2[,2]) / (Pt1[,1] - Pt2[,1]); /* Careful! Assumes x1 ^= x2 */ m = median(slope); b = median( XY[,2] - m*XY[,1] ); /* median(y-mx) */ *group=XY[c[,3],]; *lag2cvrank=XY[c[,4],]; print (b||m)[c={'Intercept' 'Slope'} L="Method=Theil Combs=All"]; print (XY); create perm1.ts_1_&I&J var {m b group lag2cvrank}; /** create data set **/ append; /** write data in vectors **/ close perm1.ts_1_&I&J ; /** close the data set **/ %MEND combination; %MACRO LOOP; %DO I=1991 %TO 1991; %DO J=0 %TO 4; %combination; %END; %END; %MEND LOOP; %LOOP; run;

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
rfrancis
Obsidian | Level 7

Problem solved. A simple USE statement qualified with WHERE does the trick. This eliminates the data step.  Thanks to everyone for your comments!  Rick

View solution in original post

5 REPLIES 5
ghosh
Barite | Level 11
Could you paste your code using the running man icon please. It's incoherent as is.
Thanks
rfrancis
Obsidian | Level 7
Sorry, used the HTML feature. SAS code below.  Thank you.  RickOPTIONS SOURCE SOURCE2 MACROGEN MPRINT;
%MACRO combination;  

data comb_1; 
	set untrimmed (keep=group lag2cvrank lag2cfo_ts lagcfo_ts);
	if group=&I and lag2cvrank eq &J;  
	*keep group lagcvrank gvkey; 
	
proc iml;
*XY = {1  9,  2 15,  3 19, 4 20, 10 45,  12 55, 18 78, /* 7 data points used by Sen (1968) */
     12.5 30,  4.5 50};                               /* 2 outliers (not considered by Sen) */
use work.untrimmed;
read all var {lag2cfo_ts lagcfo_ts group lag2cvrank} into XY;
close work.untrimmed;

*XY = {lag2cfo_ts lagcfo_ts};
/* Theil uses all "N choose 2" combinations of slopes of segments.
   Assume that the first coordinates (X) are distinct */
c = allcomb(nrow(XY), 2);        /* all "N choose 2" combinations of pairs */
group = XY[1,3];
lag2cvrank = XY[1,4];
Pt1 = XY[c[,1],];                 /* extract first point of line segments */
Pt2 = XY[c[,2],];                 /* extract second point of line segments */
slope = (Pt1[,2] - Pt2[,2]) / (Pt1[,1] - Pt2[,1]); /* Careful! Assumes x1 ^= x2 */
m = median(slope);
b = median( XY[,2] - m*XY[,1] );  /* median(y-mx) */
*group=XY[c[,3],];
*lag2cvrank=XY[c[,4],];
print (b||m)[c={'Intercept' 'Slope'} L="Method=Theil Combs=All"];
print (XY);
create perm1.ts_1_&I&J  var {m b group lag2cvrank}; /** create data set **/
append;       /** write data in vectors **/
close perm1.ts_1_&I&J ; /** close the data set **/
%MEND combination;

%MACRO LOOP; 
	%DO I=1991 %TO 1991; 
		%DO J=0 %TO 4;
			%combination; 
		%END; 
	%END;
%MEND LOOP; 

%LOOP;

run;
ballardw
Super User

If any of the statments like

*XY = {lag2cfo_ts lagcfo_ts};

are supposed to be comments then you should change them to either Macro comments

%*XY = {lag2cfo_ts lagcfo_ts};

or block comments (careful, don't nest these)

/*XY = {lag2cfo_ts lagcfo_ts};*/

Or remove the statements entirely.

The non-macro comment statement can still attempt to execute inside a macro with usually poor  results.

 

rfrancis
Obsidian | Level 7
Thank you! Very good information!
rfrancis
Obsidian | Level 7

Problem solved. A simple USE statement qualified with WHERE does the trick. This eliminates the data step.  Thanks to everyone for your comments!  Rick

sas-innovate-white.png

Join us for our biggest event of the year!

Four days of inspiring keynotes, product reveals, hands-on learning opportunities, deep-dive demos, and peer-led breakouts. Don't miss out, May 6-9, in Orlando, Florida.

 

View the full agenda.

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 1173 views
  • 1 like
  • 3 in conversation