Hi all,
My goal here is to put the analysis results into macro variables in each loop (with a loop ID of course) for future use. The code is like this:
%macro put_true_parent;
proc sql;
select D12, D13, D14, D23, D24, D34, R12, R13, R14, R23, R24, R34
into :D12_&CI._1 - :D12_&CI._2, :D13_&CI._1 - :D13_&CI._2, :D14_&CI._1 - :D14_&CI._2,
:D23_&CI._1 - :D23_&CI._2, :D24_&CI._1 - :D24_&CI._2, :D34_&CI._1 - :D34_&CI._2,
:R12_&CI._1 - :R12_&CI._2, :R13_&CI._1 - :R13_&CI._2, :R14_&CI._1 - :R14_&CI._2,
:R23_&CI._1 - :R23_&CI._2, :R24_&CI._1 - :R24_&CI._2, :R34_&CI._1 - :R34_&CI._2
from GDmeasure;
quit;
%let D12_1_CI&nCI=&&D12_&CI._1; %let D12_2_CI&nCI=&&D12_&CI._2; %let D13_1_CI&nCI=&&D13_&CI._1; %let D13_2_CI&nCI=&&D13_&CI._2;
%let D14_1_CI&nCI=&&D14_&CI._1; %let D14_2_CI&nCI=&&D14_&CI._2; %let D23_1_CI&nCI=&&D23_&CI._1; %let D23_2_CI&nCI=&&D23_&CI._2;
%let D24_1_CI&nCI=&&D24_&CI._1; %let D24_2_CI&nCI=&&D24_&CI._2; %let D34_1_CI&nCI=&&D34_&CI._1; %let D34_2_CI&nCI=&&D34_&CI._2;
%let R12_1_CI&nCI=&&R12_&CI._1; %let R12_2_CI&nCI=&&R12_&CI._2; %let R13_1_CI&nCI=&&R13_&CI._1; %let R13_2_CI&nCI=&&R13_&CI._2;
%let R14_1_CI&nCI=&&R14_&CI._1; %let R14_2_CI&nCI=&&R14_&CI._2; %let R23_1_CI&nCI=&&R23_&CI._1; %let R23_2_CI&nCI=&&R23_&CI._2;
%let R24_1_CI&nCI=&&R24_&CI._1; %let R24_2_CI&nCI=&&R24_&CI._2; %let R34_1_CI&nCI=&&R34_&CI._1; %let R34_2_CI&nCI=&&R34_&CI._2;
%global D12_1_CI&nCI D12_2_CI&nCI D13_1_CI&nCI D13_2_CI&nCI D14_1_CI&nCI D14_2_CI&nCI D23_1_CI&nCI D23_2_CI&nCI D24_1_CI&nCI D24_2_CI&nCI D34_1_CI&nCI D34_2_CI&nCI
R12_1_CI&nCI R12_2_CI&nCI R13_1_CI&nCI R13_2_CI&nCI R14_1_CI&nCI R14_2_CI&nCI R23_1_CI&nCI R23_2_CI&nCI R24_1_CI&nCI R24_2_CI&nCI R34_1_CI&nCI R34_2_CI&nCI;
%mend put_true_parent;
%macro effectsize_parent;
%do ncistart = &start %to &end %by &by;
%let nci = %eval(%eval(&ncistart) + %eval(&by)-1);
%do CI = &ncistart %to &nci;
proc surveyselect data=logireg method=srs n=&size seed=&ci.123 out=Parent_sp_&CI;
run;
%GDmeasure; /*to obtain the dominance statistics to be analyzed*/
%put_true_parent;
%end;
proc datasets lib=work memtype=data nolist; delete a: cov: ful: gd: m: parent: sp: sub: ; quit;
%end;
%mend effectsize_parent;
The second macro does some analysis and the first macro intends to put the results value from the analysis into macro variables for future use. I believe this should not be a difficult job but generate error message like this:
ERROR: Attempt to %GLOBAL a name (D12_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D12_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D13_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D13_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D14_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D14_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D23_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D23_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D24_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D24_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D34_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (D34_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (R12_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (R12_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (R13_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (R13_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (R14_1_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (R14_2_CI1) which exists in a local environment.
ERROR: Attempt to %GLOBAL a name (R23_1_CI1) which exists in a local environment.
... ...
Macro variables in the error messages are what I want to make global. There is going to be 1000 sets (24 in each set) of them. I need to identify each set with a "CI" (a % do loop variable) because they are to be referred by CI. Anybody knows how to how to make it possible?
Agree with @Reeza, this looks like there's probably a better approach to your problem. That's a LOT of macro variables you're making, and usually there are better ways to store data than macro variables. You've got a lovely dataset work.GDMeasure. SAS is really good at storing data in datasets, and letting you manipulate that data. Usually it's not a good idea to just dump a bunch of data into macro variables. Since macro variables are text, you lose precision. And generally they're a hassle to work with. (And I say that even though I'm a big fan of the macro language!)
That said, I would think you could move your long %GLOBAL statement to the top of the macro definition. As is, the PROC SQL creates them as local macro variables. As the error message says, you can't change a local macro variable into a global macro variable. For this reason, most people put a %GLOBAL or %LOCAL statement at the top of their macro. This will create all of the listed macro variables, in the specified scope.
Use a data step and CALL SYMPUTX instead to create the macro variables. One of the options within CALL SYMPUTX is to specify local or global.
OR
Rather than do this type of coding, I would highly recommend using a data step and calling the macro from the data step with more parameters, if needed, using CALL EXECUTE or DOSUBL.
It's a lot cleaner and easier to debug, and it seems like the data is already in a data set to drive it.
I wrote a basic tutorial on converting working code to a macro last week here:
https://github.com/statgeek/SAS-Tutorials/blob/master/Turning%20a%20program%20into%20a%20macro.md
The main reason I recommend this approach is how easy it is to implement and debug compared to macro loops.
Agree with @Reeza, this looks like there's probably a better approach to your problem. That's a LOT of macro variables you're making, and usually there are better ways to store data than macro variables. You've got a lovely dataset work.GDMeasure. SAS is really good at storing data in datasets, and letting you manipulate that data. Usually it's not a good idea to just dump a bunch of data into macro variables. Since macro variables are text, you lose precision. And generally they're a hassle to work with. (And I say that even though I'm a big fan of the macro language!)
That said, I would think you could move your long %GLOBAL statement to the top of the macro definition. As is, the PROC SQL creates them as local macro variables. As the error message says, you can't change a local macro variable into a global macro variable. For this reason, most people put a %GLOBAL or %LOCAL statement at the top of their macro. This will create all of the listed macro variables, in the specified scope.
The error message is clearly showing what is wrong with your code. Your logic is
Try changing the logic to
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.