2

I am trying to automate a process in SAS that alters the value of a variable in a dataset iteratively and calculates another variable for each. I am trying to get that to work as a macro within a loop, where the parameters in the inner Macro are taken as the start and end of the do loop.

So that would look like:

%Macro Outer (variable, dataset, output, i,j);

proc sql noprint;

Create table &Variable._stats as

Select *,
       min(Variable) as &Variable._min,
       max(Variable) as &Variable._max,
       range(Variable) as &Variable._range
From   &dataset;


%do &i %to &j; 

%Macro Inner (Variable, dataset, output, &&i(???), &&j(????))

data &output;
     &Variable._stats;

&Variable._2 = &Variable - (Variable._range)*&&i/&&j;
If &Variable._2 > &Variable._max then &Variable._2 = &Variable._max;
If &Variable._2 > &Variable._min then &Variable._2 = &Variable._min;

iteration = &&i;

run;

%Mend Inner;

%Mend Outer;

I will be adding more stuff to it, afterwards, but for the time being, I'm trying to ascertain the correct syntax and whether its appropriate to have the counter values from the loop be the parameters for the inner macro and how to use them in the datastep.

Pᴇʜ
  • 56,719
  • 10
  • 49
  • 73
cc143
  • 23
  • 2
  • 1
    Do NOT nest macro DEFINITIONS. The name space for macros is flat, placing the code to define one macro inside of another will just confuse you. – Tom Nov 22 '19 at 14:00

1 Answers1

0

If really want to have two macros, you can implement inner macro before outer, and inside loop just call inner macro with parameters,that you need. And you forgot about set statement in data step and %end statement. Below i try to describe this idea, but without data samples it's hard.

%Macro Inner (Variable, dataset, output, i, j);

data &output;
     set &Variable._stats;

     &Variable._2 = &Variable - (Variable._range)*&i/&j;
     If &Variable._2 > &Variable._max then &Variable._2 = &Variable._max;
     If &Variable._2 > &Variable._min then &Variable._2 = &Variable._min;

     iteration = &i;

run;

%Mend Inner;


%Macro Outer (variable, dataset, output, i,j);

proc sql noprint;

Create table &Variable._stats as

Select *,
       min(&Variable) as &Variable._min,
       max(&Variable) as &Variable._max,
       range(&Variable) as &Variable._range
From   &dataset;
quit;


%do p=&i %to &j; 
    %inner(&variable,&dataset,&output,&i,&j);
%end;
%Mend Outer;

But if i understand correctly, better to use one macro:

%Macro Outer (variable, dataset, output, i,j);

proc sql noprint;

Create table &Variable._stats as

Select *,
       min(&Variable) as &Variable._min,
       max(&Variable) as &Variable._max,
       range(&Variable) as &Variable._range
From   &dataset;
quit;


%do p=&i %to &j; 
    data &output;
        set &Variable._stats;

        &Variable._2 = &Variable - (Variable._range)*&i/&j;
        If &Variable._2 > &Variable._max then &Variable._2 = &Variable._max;
        If &Variable._2 > &Variable._min then &Variable._2 = &Variable._min;

        iteration = &i;
    run;
%end;
%Mend Outer;
Llex
  • 1,770
  • 1
  • 12
  • 27
  • Those both seem good ideas, the error I'm running into is that the loop won't run for a number of reasaons. a) I seem to have forgotten ; after do and to, and b) when it does it will spit out a not valid or used out of proper order error for i and j. – cc143 Nov 22 '19 at 12:31
  • @cc143 can you show errors and data samples, it's really hard to analyze. – Llex Nov 22 '19 at 12:52
  • @cc143 may be you forgot `quit` after `proc sql` – Llex Nov 22 '19 at 12:54
  • Unfotunately I can't extract the dataset, but this seems to be an issue I'm running into with looping variables I call in a macro in general, so I assume this is a syntax error with the do loop, where SAS doesn't like my start and end points for the loop being macro variables? – cc143 Nov 22 '19 at 12:58
  • @cc143 you didn't init varible to iterate in loop. like : `%do p=&i %to &j; ` or , for example, `%do i=1 %to &j;` – Llex Nov 22 '19 at 13:02
  • 1
    Yes, that was indeed it, I needed to create a third parameter for the loop and have that = &i s.t. %do k=&i %to &j; %inner(&var, &in, &out, &k, &j); %end; that seems to work now. Thank you. – cc143 Nov 22 '19 at 15:34