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 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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