I found a bug about SAS, a data step in a macro runs the dosubl function, the dosubl function calls the FCMP function, and the FCMP function runs the macro, which will cause the crash problem!
/*this is macro*/
%MACRO SORTS;
%LET INPUT_TABLE=%SYSFUNC(DEQUOTE(&INPUT_TABLE));
%LET VARIABLE=%SYSFUNC(DEQUOTE(&VARIABLE));
PROC SORT DATA=&INPUT_TABLE;
BY &VARIABLE;
RUN;
%MEND SORTS;
/*this is fcmp function*/
PROC FCMP OUTLIB=WORK.FUNCS.MATH;
FUNCTION SORTS_MACRO(INPUT_TABLE $,VARIABLE $);
RC=RUN_MACRO('SORTS',INPUT_TABLE,VARIABLE);
RETURN(RC);
ENDSUB;
/*this is data step and new macro*/
OPTION CMPLIB=(WORK.FUNCS);
DATA _NULL_;
RC=DOSUBL("
PROC CLUSTER DATA =&DATANAME METHOD=MCQUITTY SIMPLE CCC STD RSQUARE PSEUDO OUTTREE=&OUTNAME1;
VAR _2021 _2020 _2019 _2018;
ID CITY;
RUN;
PROC TREE DATA=&OUTNAME1 OUT=&OUTNAME2 NCLUSTERS=3;
ID CITY;
RUN;
OPTIONS CMPLIB=WORK.FUNCS;
DATA _NULL_;
RC=SORTS_MACRO('&DATANAME','CITY');
RC=SORTS_MACRO('&OUTNAME2','CITY');
RUN;");
RUN;
I personally would try to avoid all this convoluted mixture of techniques!
Try to simplify and isolate operations into their own individual units/functions/macros if you can, here is why
Take a step back, and re-analyze what's your ultimate goal from your custom code, and reevaluate what needs to be coupled vs. decoupled.
This is all I can advice you with
/*This is how the last step should be*/
%MACRO CLUSTERS (DATANAME,OUTNAME1,OUTNAME2,OUTNAME3,FILE);
OPTION CMPLIB=(WORK.FUNCS);
DATA _NULL_;
RC=DOSUBL("
PROC CLUSTER DATA =&DATANAME METHOD=MCQUITTY SIMPLE CCC STD RSQUARE PSEUDO OUTTREE=&OUTNAME1;
VAR _2021 _2020 _2019 _2018;
ID CITY;
RUN;
PROC TREE DATA=&OUTNAME1 OUT=&OUTNAME2 NCLUSTERS=3;
ID CITY;
RUN;
OPTIONS CMPLIB=WORK.FUNCS;
DATA _NULL_;
RC=SORTS_MACRO('&DATANAME','CITY');
RC=SORTS_MACRO('&OUTNAME2','CITY');
RUN;");
RUN;
%CLUSTERS(SASMAP.CLUSTERS,CLUST,TERR,SGPLOT,CLUSTERS.RTF);
Hi,
right now and with the information you provided, I can not say if and why it would make sense to write code in this way and not like this:
%MACRO CLUSTERS (DATANAME,OUTNAME1,OUTNAME2,OUTNAME3,FILE);
PROC CLUSTER DATA =&DATANAME. METHOD=MCQUITTY SIMPLE CCC STD RSQUARE PSEUDO OUTTREE=&OUTNAME1.;
VAR _2021 _2020 _2019 _2018;
ID CITY;
RUN;
PROC TREE DATA=&OUTNAME1. OUT=&OUTNAME2. NCLUSTERS=3;
ID CITY;
RUN;
PROC SORT DATA=&DATANAME.;
BY CITY;
RUN;
%MEND CLUSTERS;
%CLUSTERS(SASMAP.CLUSTERS,CLUST,TERR,SGPLOT,CLUSTERS.RTF;
- Cheers -
Why you want it to be so over-ove-over-complicated?? (yes, I repeated it 3 times)
You can achieve the same effect by simple:
/* sorting macro*/
%MACRO SORTS(INPUT_TABLE,VARIABLE);
PROC SORT DATA=&INPUT_TABLE;
BY &VARIABLE;
RUN;
%MEND SORTS;
/* This is how the last step should be... */
%MACRO CLUSTERS (DATANAME,OUTNAME1,OUTNAME2,OUTNAME3,FILE);
PROC CLUSTER DATA =&DATANAME METHOD=MCQUITTY SIMPLE CCC STD RSQUARE PSEUDO OUTTREE=&OUTNAME1;
VAR _2021 _2020 _2019 _2018;
ID CITY;
RUN;
PROC TREE DATA=&OUTNAME1 OUT=&OUTNAME2 NCLUSTERS=3;
ID CITY;
RUN;
%SORTS(&DATANAME,CITY)
%SORTS(&OUTNAME2,CITY)
%mend;
%CLUSTERS(SASMAP.CLUSTERS,CLUST,TERR,SGPLOT,CLUSTERS.RTF);
No FCMP, run_macro(), etc. (in this situation absolutely unnecessary).
Bart
I personally would try to avoid all this convoluted mixture of techniques!
Try to simplify and isolate operations into their own individual units/functions/macros if you can, here is why
Take a step back, and re-analyze what's your ultimate goal from your custom code, and reevaluate what needs to be coupled vs. decoupled.
This is all I can advice you with
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.
Ready to level-up your skills? Choose your own adventure.