BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
chris2377
Quartz | Level 8

It's a basic question but I sometimes get completely lost with loops in SAS. I am trying to use the code below to get separate bar graphs for yeach year between 1949 and 1955, but I get an error. What am I doing wrong?

 

data test;
	set sashelp.air;
	year=year(date);
	month=month(date);
run;

options mprint mlogic;
%print;
%do i=1949 to 1955 by 1;
	ods pdf file = 'c:\year_&i.pdf'
	proc sgplot data=test (where=(year=&i));
		vbar month/response=air;
		title &i;
	run;
	ods pdf close;
%end;
%mend;
1 ACCEPTED SOLUTION

Accepted Solutions
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Why do you need 1 file per graph out of interest?  As for your code:

data _null_;
  do i=1949 to 1955;
    call execute(cats('ods pdf file="c:\year_',put(i,4.),'.pdf";));
call execute(cats('title "',put(i,4.),'";')); call execute(cats('proc sgplot data=test (where=(year=',put(i,4.),')); vbar month/response=air; run;')); call execute('ods pdf close;'); end; run;

However there are two other methods to get what you want.  Firstly, and the one I would generally use, is to not output to a new file each time.  In most cases there is no need to, then you can just use by group processing, which is quicker, and simpler coding:

ods pdf file="c:\all.pdf";
proc sgplot data=test;
  by year;
  title "#byvar1";
  vbar month/response=air;
run;
ods pdf close;

Far simpler.  You could also do it in Graph Template Language, dynamic variables/conditional templates - which for this example might be a bit overkill, but it is well worth learning for more complicated graphs, good help is here: http://blogs.sas.com/content/graphicallyspeaking/

 

View solution in original post

9 REPLIES 9
Kurt_Bremser
Super User

You enclosed the filename in single quotes, suppressing resolution of the macro variable &i.

 

Edit: this was just the first problem.

 

In the %do, you must also use %to and %by, instead of "to 1955 by 1". And the "%by 1" can be omitted, as this is the default.

%macro print;
%do i=1949 %to 1955;
  ods pdf file = "c:\year_&i.pdf";
  proc sgplot data=test (where=(year=&i));
    vbar month/response=air;
    title &i;
  run;
  ods pdf close;
%end;
%mend;
%print;

 

chris2377
Quartz | Level 8

But the code doesn't wor even if I get rid of ods pdf statement at all

 

 

options mprint mlogic;
%print;
%do i=1949 to 1955 by 1;
		proc sgplot data=test (where=(year=&i));
		vbar month/response=air;
		title &i;
	run;
	%end;
%mend;
Kurt_Bremser
Super User

Take another look at my code now, had to do some edits. I also couldn't test it, as I don't have SASHELP.AIR.

If further problems persist, please post the log.

chris2377
Quartz | Level 8

Sorry, I thought sashelp files are available to every sas user. Below is the code with a sample dataset and the log message

 

data test;
	input year month air;
	datalines;
	1949 1 100
	1949 2 150
	1949 3 200
	1950 1 200
	1950 2 250
	1950 3 300
	1951 1 600
	1951 2 150
	1951 3 800
;
run;

options mprint mlogic;
%print;
%do i=1949 %to 1951;
	
	proc sgplot data=test (where=(year=&i));
		vbar month/response=air;
		title &i;
	run;
	
%end;
%mend;

And the log is:

 

 

15 data test;

16 input year month air;

17 datalines;

NOTE: The data set WORK.TEST has 9 observations and 3 variables.

NOTE: DATA statement used (Total process time):

real time 0.02 seconds

cpu time 0.03 seconds

 

27 ;

28 run;

29

30 options mprint mlogic;

31 %print;

-

180

WARNING: Apparent invocation of macro PRINT not resolved.

ERROR 180-322: Statement is not valid or it is used out of proper order.

ERROR: The %DO statement is not valid in open code.

32 %do i=1949 %to 1951;

33

34 proc sgplot data=test (where=(year=&i));

-

22

76

ERROR 22-322: Syntax error, expecting one of the following: nazwa, łańcuch w nawiasach,

stała numeryczna, stała daty i godziny, brak danych, INPUT, PUT.

ERROR 76-322: Syntax error, statement will be ignored.

-

79

ERROR 79-322: Expecting a ).

34 ! proc sgplot data=test (where=(year=&i));

-

22

WARNING: Apparent symbolic reference I not resolved.

ERROR: Błąd składniowy w warunku WHERE. <- it says "Syntax error in WHERE clause"

34 proc sgplot data=test (where=(year=&i));

-

180

ERROR 22-322: Missing ')' parenthesis for data set option list

ERROR 180-322: Statement is not valid or it is used out of proper order.

35 vbar month/response=air;

36 title &i;

WARNING: Apparent symbolic reference I not resolved.

37 run;

38

39 %end;

ERROR: The %END statement is not valid in open code.

40 %mend;

ERROR: No matching %MACRO statement for this %MEND statement.

NOTE: The SAS System stopped processing this step because of errors.

NOTE: PROCEDURE SGPLOT used (Total process time):

real time 1:41.68

cpu time 0.93 seconds

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Why do you need 1 file per graph out of interest?  As for your code:

data _null_;
  do i=1949 to 1955;
    call execute(cats('ods pdf file="c:\year_',put(i,4.),'.pdf";));
call execute(cats('title "',put(i,4.),'";')); call execute(cats('proc sgplot data=test (where=(year=',put(i,4.),')); vbar month/response=air; run;')); call execute('ods pdf close;'); end; run;

However there are two other methods to get what you want.  Firstly, and the one I would generally use, is to not output to a new file each time.  In most cases there is no need to, then you can just use by group processing, which is quicker, and simpler coding:

ods pdf file="c:\all.pdf";
proc sgplot data=test;
  by year;
  title "#byvar1";
  vbar month/response=air;
run;
ods pdf close;

Far simpler.  You could also do it in Graph Template Language, dynamic variables/conditional templates - which for this example might be a bit overkill, but it is well worth learning for more complicated graphs, good help is here: http://blogs.sas.com/content/graphicallyspeaking/

 

Rick_SAS
SAS Super FREQ

Since each plot is a bar chart, I recommend that you use the SGPANEL procedure, which will create all charts in a single panel and automatically add the category to each plot:

 


proc sgpanel data=test;
  panelby year / columns=1;
  vbar month/response=air;
run;
chris2377
Quartz | Level 8

@RW9 Thanks for the code. I'll try it. I know GTL (at least I've heard of it, not that I have great experience in this area) but I agree that for this example might be a bit overkill - I would rather do it manually 🙂 I looked at your code and I see that you used the put function. So the problem is that SAS does not treat subsequent values of i as numbers but as text? So it tries to run the code like:

 

proc sgplot data=test (where=(year="1949"))

 

while year is numeric and this causes a problem. Am I right?

 

@RW9 @Rick_SAS 

 

I know sgpanel but it is not suitable. I need a separate graph for each value of i. I just used the sashelp.air as the example. In real case it's not a graph for separate year but for separate client ID. I don't want them to be all mixed up in one file.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

With regards to your question on put to text, yes this is correct.  Call execute() is a function which takes a string, and puts it directly into the compiler after the finish of the current datastep.  So what I do within the brackets is to create a string, the put just creates a string of the four numbers.  So the final string given to the call execute is:

proc sgplot data=test (where=(year=1949))

 

Now when the compiler compiles this text, it still sees the number 1949 as it would from normal code.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 9 replies
  • 4677 views
  • 0 likes
  • 4 in conversation