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.  Rick

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;
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-wordmark-2025-midnight.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.


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
  • 1027 views
  • 1 like
  • 3 in conversation