DATA Step, Macro, Functions and more

Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statement

Accepted Solution Solved
Reply
Occasional Contributor EBB
Occasional Contributor
Posts: 14
Accepted Solution

Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statement

I have a macro code that is supposed to loop though different formats and apply those to the x axis in a line plot produced by sgplot

%let p=date wy my;
%let f=date9. weeku5. monyy5.;
%macro trend_perdiod;

                       %do I=1 %to %sysfunc(countw(&p.));

                               %let pp=%scan(&p.,&I.);

                               %let TF=%scan(&f.,&I.);

                               proc means data=Insas.&sn. noprint;

                                class &pp.;

                                freq w;

                                      output out=insas.&pp._&sn. mean=mean;

                               run;

                               *save mean value for time period;

                               proc sql noprint;

                                      select Mean into: Tmean separated by ' '

                                      from insas.&pp._&sn.

                                      where &pp.=.;

                               quit;

                               data insas.&pp._&sn.;

                                      set insas.&pp._&sn.;

                                      where &pp. ne .;

                                      lag_M=lag(mean);

                                      leakage=-(Lag_M-mean)/Lag_M;

                                      format leakage percentn12.2;

                               run;

                               *Plot;

                               Title1 bcolor=gold " &SN. - Average &Pp.";

                               proc sgplot data=insas.&pp._&sn.;

                                      xaxis TICKVALUEFORMAT=&TF.;

                                      series x=&pp. y=mean / markers;

                                      refline &Tmean. /axis=y label=("Avg=&Tmean.");

                                      yaxis grid;

                               run;

                               Title1;

                               proc print data=insas.&pp._&sn.;

                                      var &pp. mean leakage;

                                      format mean 12.2;

                               run;

                       %end;

               %mend trend_perdiod;

               %trend_perdiod;

The issue that I have is that the &TF. macro variable is not correctly resolved and I get the following error: 

ERROR 772-580: Syntax error: expecting a constant or a dynamic.

 

Any idea how to enclose my list of formats so that they are properly applied into the following statement?

xaxis TICKVALUEFORMAT=&TF.

Any help is appreciated! Thanks a lot!


Accepted Solutions
Solution
‎02-05-2018 01:47 AM
Super User
Posts: 6,935

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

Here's some of the detail about why that would work:

 

https://v8doc.sas.com/sashtml/macro/z514scan.htm

 

By default, %SCAN uses a dot as a delimiter.  So %SCAN is not picking up the dot at the end of the words within &F, when computing a value for &TF.  It's possible this would also work, but I can't test it right now:

 

%scan(&f., &i, )

 

 

View solution in original post


All Replies
Super User
Super User
Posts: 9,853

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

My, what a total ballache.  You know, if you did one simple change then that whole block of code would disappear, instead looping over the whole code, process your data once, then call a macro to do the sglpot, (not tested this, just off the top of my head):

proc means data=insas.yourds noprint;
  by pp;
  var date wy my;
  output out=means mean(date)= mean(wy)= mean(my)= / autoname;
run;

data insas.yourdata;
  merge insas.yourds means;
  by pp;
run;

%macro plot (var=,fmt=);

  proc sglpot data=insas.yourds;
    xaxis tickvalueformat=&fmt..;
    series x=&var. ...
    refline &var._mean / ...
  run;

%mend plot;

%plot (var=date,fmt=date9);
%plot (var=wy,fmt=weeku5);
%plot (var=my,fmt=monyy5);

Saying that, you could probably modify the underlying proc template code on that, and not need to use the 3 macro calls at all, but I doubt that will show any less code.

With regards to your question on the error, how can we tell unless you post the relevant log section?  It is telling you there is something wrong, enable debugging - options mlogic mprint symbolgen; - and then look at the log this will tell you what is wrong.  I suspect it maybe the passing of . as well, scan maybe using that as a delimiter.  Drop that from the string then use &tf.. - note the two dots, one to finish the macro variable, one to indicate its a format.  And avoid mixing upper case and lower case it really makes code hard to read (and use the code window - its the {i} above post area) to retain code formatting.

 

Trusted Advisor
Posts: 1,848

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

Use options mprint symbolgen; and check the log - what value has &TF.

 

If need more help - please post the whole log.

Super User
Posts: 10,588

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

Another reason why working from lists in macro variables is sub-optimal:

%let p=date wy my;
%let f=date9. weeku5. monyy5.;
%macro trend_perdiod;
%do I=1 %to %sysfunc(countw(&p.));
  %let pp=%scan(&p.,&I.);
  %let TF=%scan(&f.,&I.);
  %put pp="&pp.";
  %put tf="&tf.";
%end;
%mend;
%trend_perdiod

data control;
input p $ f $;
cards;
date date9.
wy weeku5.
my monyy5.
;
run;

%macro testmac(p,f);
%put p="&p.";
%put f="&f.";
%mend;

data _null_;
set control;
call execute('%nrstr(%testmac(' !! trim(p) !! ',' !! trim(f) !! '));');
run;

Just compare the logs.

You could make it work by using an artificial delimiter:

%let p=date wy my;
%let f=date9.@weeku5.@monyy5.;
%macro trend_perdiod;
%do I=1 %to %sysfunc(countw(&p.));
  %let pp=%scan(&p.,&I.);
  %let TF=%scan(&f.,&I.,@);
  %put pp="&pp.";
  %put tf="&tf.";
%end;
%mend;
%trend_perdiod

but I really prefer to work off datasets with call execute().

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
How to convert datasets to data steps
How to post code
Super Contributor
Posts: 359

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

Posted in reply to KurtBremser

Hello,

 

keeping the space as delimiter and using %scan(&f.,&I.,' ') or %scan(&f.,&I.,%str( )) also works.

Solution
‎02-05-2018 01:47 AM
Super User
Posts: 6,935

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

Here's some of the detail about why that would work:

 

https://v8doc.sas.com/sashtml/macro/z514scan.htm

 

By default, %SCAN uses a dot as a delimiter.  So %SCAN is not picking up the dot at the end of the words within &F, when computing a value for &TF.  It's possible this would also work, but I can't test it right now:

 

%scan(&f., &i, )

 

 

Super Contributor
Posts: 359

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

Posted in reply to Astounding

Since the compiler ignores spaces, quotes or %str( ) are needed to tell the compiler that the space is significant.

 

114  %let x=a. b. c.;
115
116  %macro test_scan;
117      %do i=1 %to %sysfunc(countw(&x.));
118          %put ---;
119          %let a=%scan(&x.,&i.);
120          %put &=a.;
121
122          %let b=%scan(&x.,&i., );
123          %put &=b.;
124
125          %let c=%scan(&x.,&i.,' ');
126          %put &=c.;
127      %end;
128  %mend;
129
130  %test_scan;
---
A=a
B=a. b. c.
C=a.
---
A=b
B=
C=b.
---
A=c
B=
C=c.
Super User
Posts: 6,935

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

Thanks for testing.  What a strange result for &B.  I can't explain it off the top of my head, but I will try running some tests later.

 

Also note that using ' ' as the delimiter does use blanks as a delimiter.  But it also uses single quotes as a delimiter.  For practical purposes that almost never makes a difference.

Super Contributor
Posts: 359

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

[ Edited ]
Posted in reply to Astounding

Maybe having a void third argument means that no delimiter will be used so we'll always

obtain the entire string with 1 as second argument and an empty string for higher values.

 

The behavior is different with the scan function :

 

197  data _NULL_;
198  str="a b c";
199  first=scan(str,1,'');
200  put first=;
201  run;

first=a
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

Edit : The result above is due to the fact that empty strings in SAS contain one space. I tried the same program, omitting

the third argument. I thought it would result in an error but it produces the same result as its macro counterpart :

 

202  data _NULL_;
203  str="a b c";
204  first=scan(str,1,);
205  put first=;
206  run;

first=a b c
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

 

From the documentation

http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000214639.htm

Syntax

SCAN(string, count<,charlist <,modifiers>>)

Using Null Arguments

The SCAN function allows character arguments to be null. Null arguments are treated as character strings with a length of zero. Numeric arguments cannot be null.


Occasional Contributor EBB
Occasional Contributor
Posts: 14

Re: Macro variable containing a list of format that need to be applied to a proc sgplot xaxis statem

For other people looking for the same answer: It is also working is the . is left out of the list and added when the macro variable is called.

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 9 replies
  • 226 views
  • 1 like
  • 6 in conversation