Xia.Song
Xia.Song

Reputation: 426

how can I build a loop for macro in SAS?

I want to do a simulation based on macro in SAS. I can build a function named 'fine()', the code is as follows

DATA CLASS;
INPUT NAME $ SEX $ AGE HEIGHT WEIGHT;
CARDS;
ALFRED  M  14  69.0 112.5
ALICE   F  13  56.5  84.0
BARBARA F  13  65.3  98.0
CAROL   F  14  62.8 102.5
HENRY   M  14  63.5 102.5
RUN;
PROC PRINT;
    TITLE 'DATA';
RUN;
proc print data=CLASS;run;

PROC FCMP OUTLIB = work.functions.func;
function populationCalc(HEIGHT,WEIGHT,thres);
pop=HEIGHT-WEIGHT-thres;
return (pop);
ENDSUB;

options cmplib=(work.functions);
%macro fine(i);
data ex;
set CLASS;
thres=&i;
pop = populationCalc(HEIGHT,WEIGHT,thres);
if (pop>50) then score=1;
else score=0;
run;

proc iml;
USE ex;
READ all var _ALL_ into ma[colname=varNames];
CLOSE ex;
nn=nrow(ma);
total_score=sum(ma[,'thres']);
avg_score=sum(ma[,'thres'])/nn; 
print total_score avg_score;
%mend fine;

%fine(10);
%fine(100);
%fine(150);

I want to build a loop for function 'fine()' ans also use macro, but the result is not as I expect. How can I fix this?

%macro ct(n);
data data_want;
%do i=1 %to &n;
x=%fine(&i);
output x;
%end;
run;
%macro ct;

%ct(10);

Upvotes: 0

Views: 68

Answers (1)

Richard
Richard

Reputation: 27498

%fine does not generate any text that can be used in the context of a right hand side (RHS) of a DATA Step variable assignment statement.

You seem to perhaps want this data set as a result of invoking %ct

i total_score average_score
- ----------- -------------
1      5           1
2     10           2
3     15           3
etc...

Step 1. Save IML result

Add this to the bottom of IML code in %fine, replacing the print

create fine_out var {total_score avg_score};
append;
close fine_out;
quit;

Step 2. Rewrite ct macro

Invoke %fine outside a DATA step context so the DATA and IML steps can run. Append the IML output to a results data set.

%macro ct(n,out=result);
  %local i;
  %do i=1 %to &n;
    %fine(&i)
    %if &i = 1 %then %do;
      data &out; set fine_out; run;
    %end;
    %else %do;
      proc append base=&out data=fine_out; run;
    %end;
  %end;
%mend;

options mprint;

%ct(10)

This should be the output WORK.RESULT based on your data

enter image description here

Upvotes: 1

Related Questions