I have attached a SAS program file here. I just want to store some values as macro variables (not a difficult thing), but I keep getting the warning that the symbolic references are not resolved. Can anyone explain why?
When I don't use a macro or the %do loop and just specify:
%let i=1;
...run PROC SQL...
%let i=2;
...run PROC SQL...
%let i=3;
...run PROC SQL...
and then run the code, everything works fine, but I need to do loop since the number of groups changes.
I was able to get it to work. I replaced lines 169-202 with the following code:
%do i=1 to &ngroups;
proc sql noprint;
select left into :risk&i separated by '|' from estimate where stratum=&i;
quit;
%end;
%do i=0 %to &nticks;
%let tickstat&i = %str(tick=) %eval(&i+1) j=c "&&tick&i" j=c;
%if &i=0 %then %do;
%let tickstat&i=&&tickstat&i j=c "&&header&j" " %scan(&&risk1,%eval(&i+1),"|")";
%do j=2 %to &ngroups;
%let tickstat&i=&&tickstat&i j=c "&&header&j" " %scan(&&risk&j,%eval(&i+1),"|")";
%end;
%end;
%else %do;
%let %let tickstat&i=&&tickstat&i ' ' j=c "%scan(&risk1,%eval(&i+1),"|")";
%do j=2 %to &ngroups;
%let tickstat&i=&&tickstat&i j=c "%scan(&&risk&j,%eval(&i+1),"|")";
%end;
%end;
%end;
I would think you are getting that result because all of the macro variables are local. Does the following produce what you were expecting? The only change I made was to move your %put statements into your macro:
data estimate;
input stratum left @@;
datalines;
1 3 1 1 1 1
1 0 1 0 1 0
1 0 1 0 1 0
1 0 1 0 2 22
2 19 2 6 2 1
2 1 2 1 2 0
2 0 2 0 2 0
2 0 3 14 3 13
3 8 3 3 3 1
3 1 3 1 3 1
3 1 3 1 3 1
;
run;
%macro test;
%let ngroups=3;
%let nticks=11;
%let maxtick=%eval(&nticks-1);
%do i=1 %to &ngroups;
%let i=%sysfunc(compress(&i));
proc sql noprint;
select left into :risk&i.00-:risk&i.&maxtick. from estimate where stratum=&i.;
quit;
%end;
%put &risk100;
%put &risk101;
%put &risk102;
%put &risk103;
%put &risk104;
%put &risk105;
%put &risk106;
%put &risk107;
%put &risk108;
%put &risk109;
%put &risk110;
%put &risk200;
%put &risk201;
%put &risk202;
%put &risk203;
%put &risk204;
%put &risk205;
%put &risk206;
%put &risk207;
%put &risk208;
%put &risk209;
%put &risk210;
%put &risk300;
%put &risk301;
%put &risk302;
%put &risk303;
%put &risk304;
%put &risk305;
%put &risk306;
%put &risk307;
%put &risk308;
%put &risk309;
%put &risk310;
%mend test;
%test
I thought if I would have resolved this issue that my whole program would have worked. Your method did fix my problem that I presented, but inside the larger macro that I am actually using, I try to call each &riskXXX variable, but it still says that they are not found resolved even though I am inside the macro calling local variables.
Can you post an example?
What are you actually trying to do? In general I rarely find it useful to generate so many macro variables.
You might consider just using a few variables with the multiple values stores as delimited lists in these variables.
I am trying to put the number of patients at risk at the bottom of a Kaplan-Meier survival plot. I am trying to adapt the %survivalplot macro from the 2011 MWSUG conference:
http://www.mwsug.org/prohttp://www.mwsug.org/proceedings/2011/coders/MWSUG-2011-CC08.pdf
I have thought that there might be a simplier way (like putting all the at-risk values in one variable separated by a "|" and then using the scan() function to loop through the variable). I may just play around with those ideas and see if I can get something more efficient to work.
Thanks Tom and Art!
By the way, if you are reading the link above, I am having these issues under the "Axis2 Statement" on page 10.
I still think the Forum would do better seeing the code you are actually running and the specific errors you are getting and at which specific lines.
Art,
I have attached the full SAS code as well as a csv file to import. (The import code is included). Just remember to change the file locations for importing the csv data (line 259) and the output file path in the %survivalplot macro call (variable is figpathname on line 268).
My issues are starting on line 176 in the %do loop where it is trying to call all the &risk variables.
I also have 2 SAS files attached here. I could not remove the first one. You need to use the one where the PROC IMPORT statement starts on line 259 (not line 251).
Thanks!
I don't see any attachments
See if that works. If not, send me a message to dbateman@endocyte.com. I will e-mail you the code and data.
Yes, that worked, but I'm not familiar enough with the procs to follow what is happening at each step.
One obvious error, though, is in your macro variable assignments in your proc sql code. You are trying to create a range between, say, 200 and 29. Obviously, I don't think that it what you are really trying to do.
I was able to get it to work. I replaced lines 169-202 with the following code:
%do i=1 to &ngroups;
proc sql noprint;
select left into :risk&i separated by '|' from estimate where stratum=&i;
quit;
%end;
%do i=0 %to &nticks;
%let tickstat&i = %str(tick=) %eval(&i+1) j=c "&&tick&i" j=c;
%if &i=0 %then %do;
%let tickstat&i=&&tickstat&i j=c "&&header&j" " %scan(&&risk1,%eval(&i+1),"|")";
%do j=2 %to &ngroups;
%let tickstat&i=&&tickstat&i j=c "&&header&j" " %scan(&&risk&j,%eval(&i+1),"|")";
%end;
%end;
%else %do;
%let %let tickstat&i=&&tickstat&i ' ' j=c "%scan(&risk1,%eval(&i+1),"|")";
%do j=2 %to &ngroups;
%let tickstat&i=&&tickstat&i j=c "%scan(&&risk&j,%eval(&i+1),"|")";
%end;
%end;
%end;
One approach would be to make all your &RISK variables global. If that sounds acceptable, here is one way to do it. Here's what you started with:
%do i=1 %to &ngroups;
%let i=%sysfunc(compress(&i));
proc sql noprint;
select left into :risk&i.00-:risk&i.&maxtick. from estimate where stratum=&i.;
quit;
%end;
Here's a replacement. (Other changes, such as moving the PROC statement and removing a %LET statement are made on purpose not by accident):
%local i j;
proc sql noprint;
%do i=1 %to &ngroups;
%do j=0 %go &maxtick;
%global risk&i%sysfunc(putn(&j,z2));
%end;
select left into : risk&i.00-:risk&i.%sysfunc(putn(&maxtick,z2)) from estimate where stratum=&i;
%end;
quit;
Once the &RISK variables are global, I suspect the rest of the code would work.
Good luck.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.