Data Step Macro

Reply
Occasional Contributor
Posts: 14

Data Step Macro

Hello, 

 

I'm trying to convert the following code to a macro, but I'm not able to do so.  My original code and my attempt at the macro are below. 

 

Thank you for your help,

Phil

 

/** Original Code **/
data final.index;
set final.index_join;
if s_weight = 1 and Total_Aplus > 0 then selection_Aplus = (total_Aplus/zip_qual_capacity)*s_weight;
else selection_Aplus = 0;
if s_weight = 0.67 and Total_A > 0 then selection_A = (total_A/zip_qual_capacity)*s_weight;
else selection_A = 0;
if s_weight = 0.33 and Total_Bplus > 0 then selection_Bplus = (total_Bplus/zip_qual_capacity)*s_weight;
else selection_Bplus = 0;
if s_weight = -0.33 and Total_B > 0 then selection_B = (total_B/zip_qual_capacity)*s_weight;
else selection_B = 0;
if s_weight = -0.67 and Total_C > 0 then selection_C = (total_C/zip_qual_capacity)*s_weight;
else selection_C = 0;

run;

 

/** Macro Attempt **/
%LET sweight1=-0.67;
%LET sweight2=-0.33;
%LET sweight3=0.33;
%LET sweight4=0.67;
%LET sweight5=1;
%LET level1 = _C;
%LET level2 = _B;
%LET level3 = _Bplus;
%LET level4 = _A;
%LET level5 = _Aplus;

%MACRO q_index;
%DO j = 1 %TO 5;
%DO k = 1 %TO 5;
data final.index_b;
set final.index;
/** Calculate the quotient index with negative/positive weights **/
%if "s_weight" = "&&sweight&j" and "Total&&level&k" > 0 %then
%let selection&&level&k = (total&&level&k/zip_qual_capacity)*&&sweight&j;
%else %let selection&&level&k = 0;
RUN;
%end;
%end;
%MEND q_index;

%q_index;

Super User
Posts: 19,877

Re: Data Step Macro

Posted in reply to PhillipSherlock

Wouldn't arrays be easier?

Super User
Posts: 19,877

Re: Data Step Macro

Array method:

Also, be careful with comparisons with decimal numbers (=0.33) you may run into numerical precision issues. 

 

data final.index;
set final.index_join;

array s_weights(5) _temporary_ (1 0.67 0.33 -0.33 0.67);
array var_total(5) total_aplus total_a total_bplus total_b total_c;
array var_sel(5) selection_aplus selection_a selection_bplus selection_b selection_c (5*0);

do i=1 to 5;
if s_weight = sweights(i) and var_total(i)>0 then var_sel(i)= (var_total(i)/zip_qual_capacity)*s_weight;
end;

run;
Super User
Posts: 5,518

Re: Data Step Macro

Posted in reply to PhillipSherlock

While I agree with Reeza and would likely choose arrays for this application, it's not a bad application for learning macro language.  Here's a half-done version, where you will have to figure out what goes in the %DO loop.

 

%macro q_index (in_dsn=, out_dsn=, weight_list=, level_list=);

%local i;

data &out_dsn;

set &in_dsn;

%do i=1 %to 5;

   **** Something goes here !;

%end;

run;

%mend q_index;

 

Then the macro call might look like this:

 

%q_index (in_dsn=final.index_join, out_dsn=final.index, weight_list=0.67 0.33 0.33 0.67 1, level_list=_C _B _Bplus _A _Aplus)

 

The next step, if you are so inclined, would be to change the hard-coding of the loop from 1 to 5.  Instead, have the macro count how many weights you have, and generate the matching number of IF/THEN statements.

Ask a Question
Discussion stats
  • 3 replies
  • 306 views
  • 0 likes
  • 3 in conversation