I have a dataset that looks like this:
DXCODE NUMBER
78060 1
7784 2
09989 3
I am trying to create 3 global macro variables called "macrovariable1", "macrovariable2", and "macrovariable3", which have the DXCODE values "78060", "7784", and "09989", respectively.
Here is my macro:
%macro macrovariables;
%do i=1 %to 3;
data _null_;
set codes;
where number = &i;
call symput('macrovariable' || trim(left(&i)), '"' || trim(left(dxcode)) || '"');
run;
%end;
%mend macrovariables;
I want this macro to replicate the following code:
data _null_;
set codes;
where number = 1;
call symput('macrovariable1', "78060");
run;
data _null_;
set codes;
where number = 1;
call symput('macrovariable1', "78060");
run;
data _null_;
set codes;
where number = 2;
call symput('macrovariable2', "7784");
run;
data _null_;
set codes;
where number = 3;
call symput('macrovariable3', "09989");
run;
Unfortunately, this code does not generate the global macro variables that I want. What am I doing wrong? Thanks.
Chuakp,
If you look in my log, my code produced three local macro variables. If you need the macro variables to be global, then simply add a statement to define them as such "%global Macrovariable&i." immediately after the do i=1 to 3 statement. It worked for me.
It looks like your problem lies in the first argument to CALL SYMPUT. Part of that would look like this on the third iteration:
trim(left(3))
You would expect the DATA step to complain that it can't apply the LEFT function to the number 3, it can only apply it to a character string. Try a simpler version for the first argument that uses double quotes instead of single:
call symput("macrovariable&i", ...
That should take care of the problem.
Thanks for the suggestion. I changed the code to:
call symput("macrovariable&i", '"' || trim(left(dxcode)) || '"');
I am still not getting this to work despite the change, unfortunately.
Chuakp,
Try this:
%macro macrovariables;
%do i=1 %to 3;
%let mv = macrovariable;
data _null_;
set codes;
where number = &i.;
call symput("macrovariable&i.",trim(left(dxcode)));
run;
%end;
%mend macrovariables;
180 %macro macrovariables;
181
182 %do i=1 %to 3;
183 %let mv = macrovariable;
184 data _null_;
185 set codes;
186 where number = &i.;
187 call symput("macrovariable&i.",trim(left(dxcode)));
188 run;
189 %put "macrovariable&i. = &&&mv.&i.";
190 %end;
191
192 %mend macrovariables;
193
194 %macrovariables;
NOTE: There were 1 observations read from the data set WORK.CODES.
WHERE number=1;
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
"macrovariable1 = 78060"
NOTE: There were 1 observations read from the data set WORK.CODES.
WHERE number=2;
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
"macrovariable2 = 7784"
NOTE: There were 1 observations read from the data set WORK.CODES.
WHERE number=3;
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
"macrovariable3 = 09989"
Thanks jwillis - unfortunately, that code does not quite get me where I need to be. I am able to get the same SAS log output as you pasted above, but this code does not result in the creation of three global macro variables (macrovariable1-macrovariable3).
Chuakp,
If you look in my log, my code produced three local macro variables. If you need the macro variables to be global, then simply add a statement to define them as such "%global Macrovariable&i." immediately after the do i=1 to 3 statement. It worked for me.
Thanks! This worked.
Using your code, I've been able to set global macro variables (where macrovariable1 = 78060, macrovariable2 = 7784, etc.). I'm trying to figure out the right way to reference these macro variables in a %do loop.
%macro admissiondx;
%do j=1 %to 100;
data codes;
if admit_dx = "¯ovariable&j." then flag = 1; /*I want this to read: if admit_dx = "78060" then flag = 1;*/
if flag > 0 then output;
drop flag;
run;
%end;
%mend admissiondx;
When I run the above code, I get a warning from SAS: "WARNING: Apparent invocation of macro MACROVARIABLE1 not resolved." I feel like there's some small change in syntax that I need to make but can't figure it out. Do you have any ideas? Thanks in advance - you've been really helpful and I appreciate it.
Chuakp,
1. Add this anywhere in your code before #2.
%let mv = macrovariable;
2. Change this: if admit_dx = "¯ovariable&j." to this: if admit_dx = "&&&mv.&j."
3. Test #2 with this anywhere after #2.
%put "macrovariable&j. = &&&mv.&j.";
Sounds like it would be better to make a format than a series of macro variables.
You don't need the macro loop and WHERE to create a macro variable from each observation of DXCODE data. Also use SYMPUTX to make the variable global if that's what you need.
Thanks for the tip.
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
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.