BookmarkSubscribeRSS Feed
d6k5d3
Pyrite | Level 9

 

I have the following code running:

%macro central_bank (reg, begin, end); 
									   
%do i= &begin. %to &end.;

data &reg.&i.;
set &reg.&i.;

if Code= "US28" or Code= "US29" then do;
if Actual= 9999 or Surv_Med= 9999 then delete;

Surp_B_&reg.&i.= Surp_Bloom;
SD_B_&reg.&i.= Std_Dev_Surv;

Diff_&reg.&i.= Actual-Surv_Med;
Ratio_&reg.&i.= Actual/Surv_Med; end;

PS_&reg.&i.= 1;
Year= year (Date);
Interval= (int(Time)/300)+1;
run;

proc sort data= &reg.&i.;
by Date Interval;
run;

%if &begin.= 28 or &begin.= 29 %then %do;

proc sql;
create table C_&reg.&i. as
select *, STD(Diff_&reg.&i.) as SD_&reg.&i., Diff_&reg.&i./STD(Diff_&reg.&i.) as Surp_&reg.&i. from &reg.&i.;
quit;

proc means data= C_&reg.&i. nway noprint;
class Year;
output out= YSC_&reg.&i. STD(Diff_&reg.&i.)= YSD_&reg.&i.;
run;

proc sort data= C_&reg.&i.;
by Date Year;
run;

proc sort data= YSC_&reg.&i.;
by Year;
run;

data C_&reg.&i.;
merge C_&reg.&i. YSC_&reg.&i.;
by Year;
run;

proc sort data= C_&reg.&i.;
by Date Interval;
run;

data C_&reg.&i.;
set C_&reg.&i.;

YSurp_&reg.&i.= Diff_&reg.&i./YSD_&reg.&i.;
run;

data C_&reg.&i.;
set C_&reg.&i.;

keep Date Time Interval PS_&reg.&i. Diff_&reg.&i. SD_&reg.&i. SD_B_&reg.&i. YSD_&reg.&i. Surp_&reg.&i. Surp_B_&reg.&i. YSurp_&reg.&i. Ratio_&reg.&i.;
run;

%end;

%else %if &begin.= 30 or &begin.= 31 %then %do;

data C_&reg.&i.;
set &reg.&i.;

keep Date Time Interval PS_&reg.&i.;
run;

%end;

%end;

%mend central_bank;

%central_bank (US, 28, 31);

Though I have coded so that some part of the code gets executed for a certain value of the macro variable, I see that the whole code gets run, and %if condition does not work.

 

Where did I go wrong?

 

Much thanks.

 

Regards.

3 REPLIES 3
Kurt_Bremser
Super User

First, write your code in structured way that lets you see logical blocks; as it is, that ugly spaghetti is close to un-decipherable. See Maxim 12.

Next, use %put to follow your macro logic:

%macro central_bank (reg, begin, end); 
									   
%do i = &begin. %to &end.;

  %put loop iteration for &i.;


  %if &begin.= 28 or &begin.= 29 %then %do;

    %put branch for begin in (28,29);

  %end;

  %else %if &begin.= 30 or &begin.= 31 %then %do;

    %put branch for begin in (30,31);

  %end;

%end;

%mend central_bank;

%central_bank (US, 28, 31);

The log from that (see Maxim 2) tells you that your second %if prevents the second block from executing:

37         %macro central_bank (reg, begin, end);
38         									
39         %do i = &begin. %to &end.;
40         
41           %put loop iteration for &i.;
42         
43         
44           %if &begin.= 28 or &begin.= 29 %then %do;
45         
46             %put branch for begin in (28,29);
47         
48           %end;
49         
50           %else %if &begin.= 30 or &begin.= 31 %then %do;
51         
52             %put branch for begin in (30,31);
53         
54           %end;
55         
56         %end;
2                                                          Das SAS System                         07:58 Wednesday, February 13, 2019

57         
58         %mend central_bank;
59         
60         %central_bank (US, 28, 31);
loop iteration for 28
branch for begin in (28,29)
loop iteration for 29
branch for begin in (28,29)
loop iteration for 30
branch for begin in (28,29)
loop iteration for 31
branch for begin in (28,29)
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Sideways to your question, you would save yourself

- A lot of coding and maintenance

- A lot of processor and storage space

Simply by changing your approach to your problem.  I can tell this as soon as I see coding like:

data &reg.&i.;

and

Surp_B_&reg.&i.

 This shows that your are creating lots of datasets for the same data and that in those datasets you are creating lots of variables.  Both of these show a badly worked out data modelling structure.

Without seeing the data/process in full my suggested change would be to create a record (observation) for each of the data items like:

PARAM               RESULT...

SURP_B_US_1  ....

SURP_B_US_2  ...

Then instead of creating a new dataset (i.e. read/writes for each group) use a by group to do the calculations in one simple datastep/means output by your by groups and params, to get one complete results dataset out.  This would give you 1 dataset in, 1 dataset out (1*read/write) and very simple Base SAS which is easy to code and maintain.  The only reason for transposed data is for output purposes and this can be achieved by a proc transpose before proc report.

Reeza
Super User
If you have any option to modify this code I would strongly recommend removing the macro logic entirely and switching to data step. It's faster, more efficient and easier to maintain in the long run.

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 3 replies
  • 652 views
  • 3 likes
  • 4 in conversation