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 open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
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.