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
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.