0
votes

This code takes two macros and assigns them to arrays inside a data step, then loops through each variable defined in ln_vars, creating a new variable which is the natural log of the variable, appending _ln to the name

%let ln_vars = var1 var2;
%let ln_names = %add_string(&ln_vars, _ln);

data transform;
    set analysis;
    array ln &ln_vars;
    array ln_n &ln_names;
    *call execute ('%add_string(%str(&ln_vars), _ln)');

do over ln;
    ln_n = log(ln);
end;

run;

maybe there's a better idiom in sas code (I hope). I want to be able to just pass a single macro (the ln_vars macro) and call the %add_string() function from inside the data step. The commented 'call execute' returns the correct string, but when I try to

1588       array ln_n call execute ('%add_string(%str(&ln_vars), _ln)');
ERROR: Attempt to initialize variable call in numeric array ln_n with character constant
       '%add_string(%str(&ln_vars), _ln)'.
1
Before you try to automate, write code that executes successfully for one observation in analysis. Post that code (and sample data) and it will be easier to help. - Jay Corbett
the code above works. I want to replace &ln_names in the data step with some version of the call execute command commented out below it. - justin cress

1 Answers

2
votes

It would help if you gave us the definition of the %add_string macro. In any case, it looks like you need &ln_names to be a list of variables matching the list in &ln_vars except each variable has the suffix '_ln'.

If I'm correct, you don't really need the %add_string macro and could do this instead:

%let ln_vars = var1 var2;
%let ln_names = %sysfunc(tranwrd(&ln_vars,%str( ),%str(_ln )))_ln;
%put LN_VARS: &ln_vars;
%put LN_NAMES:&ln_names;

data transform;
  set analysis;
  array ln &ln_vars;
  array ln_n &ln_names;
  do over ln;
    ln_n = log(ln);
  end;
run;

Note that the two %put statements are not really necessary - they are just placed there to inspect the values of the two macro variables


As per your comment, you could have a macro:

%macro lnvars(vars=,suffix=_ln);

  %let newvars=%sysfunc(tranwrd(&vars,%str( ),%str(&suffix )))&suffix;

  array ln &vars.;
  array ln_n &newvars.;
  do over ln;
    ln_n = log(ln);
  end;

%mend;

and then call the macro from your data step as follows:

data transform;
  set analysis;
  %lnvars(vars=var1 var2);
run;

(Note, I've not tested the code, but you should get the general idea)