/*****************************************************************/
 /*** TIP 00407                                                 ***/
 /*** repeatfn.sas                                              ***/
 /*** Author:  Charles Patridge                                 ***/
 /***                                                           ***/
 /*** Purpose is to apply the same function for a list of sas   ***/
 /***  variables where function requires only a single variable.***/
 /***  It then creates the sas variables of the output of the   ***/
 /***  desired function and keeps them in the same dataset.     ***/
 /***                                                           ***/
 /*** User needs to be careful of the functions called on       ***/
 /***  certain variables for appropriate values.                ***/
 /***                                                           ***/
 /*** 1st parameter: name of file to put temp sas code into.    ***/
 /***                                                           ***/
 /*** 2nd parameter: list of sas vars for function to be        ***/
 /***                  applied to.                              ***/
 /***                                                           ***/
 /*** 3rd parameter: prefix for output var name                 ***/
 /***                                                           ***/
 /*** 4th parameter: function to be repeated                    ***/
 /***                                                           ***/
 /*** Names of SAS Variables should be short enough to apply    ***/
 /*** the user supplied prefix to not exceed max length of      ***/
 /*** a SAS variable (32 characters)                            ***/
 /***                                                           ***/
 /***                                                           ***/
 /*** Only makes sense if you need to do the same function for  ***/
 /***   many sas variables (say more than 20)                   ***/
 /*****************************************************************/

%MACRO repeatfn( _tmpfile_ , _varlist_, _prefix_, _function_ );
  options noxwait;
  x del &_tmpfile_ ; /*** delete tmp file to be sure it is clean ***/
                     /*** need to use appropriate OS command to delete file ***/
  filename mytmp "&_tmpfile_" ; /*** file where sas code will be saved ***/
  data _null_ ;
   file mytmp notitle;
  /*** determine number of SAS variables being called ***/
  number = 1 + ( length(trim("&_varlist_")) - length(compress("&_varlist_")) );
  DO J=1 TO NUMBER;
   word = scan( "&_varlist_", j );
   /*** build the appropriate sas code for function called ***/
   string = "&_prefix_"        || left(trim(word)) ||
            " =  &_function_(" || left(trim(word)) || ');';
   put string;
  END;
  run;
%MEND repeatfn;

 /*** example of using and calling the repeatfn macro ***/
 /*** example created for Windows OS platform ***/
 /*** need to use appropriate file naming convention for your OS ***/
 %let tempfila = c:\download\tmplog.txt;
 %let tempfilb = c:\download\tmpexp.txt;
 %let tempfilc = c:\download\tmpcos.txt;
 %let tempfild = c:\download\tmpabs.txt;

 %repeatfn ( &tempfila ,  x y z, ln_ , log  ); /*** do log function ***/
 %repeatfn ( &tempfilb ,  x y z, ex_ , exp  ); /*** do exp function ***/
 %repeatfn ( &tempfilc ,  x y z, co_ , cos  ); /*** do cos function ***/
 %repeatfn ( &tempfild ,  x y z, ab_ , abs  ); /*** do abs function ***/

 data test;
  x = 1.5;
  y = -2.0;
  z = 3.5;
  %include "&tempfila";
  %include "&tempfilb";
  %include "&tempfilc";
  %include "&tempfild";
 run;

  /***
  tmplog.txt will contain:
      ln_x =  log(x);
      ln_y =  log(y);
      ln_z =  log(z);

  tmpexp.txt will contain:
      ex_x =  exp(x);
      ex_y =  exp(y);
      ex_z =  exp(z);

  tmpcos.txt will contain:
      co_x =  cos(x);
      co_y =  cos(y);
      co_z =  cos(z);

  tmpabs.txt will contain:
      ab_x =  abs(x);
      ab_y =  abs(y);
      ab_z =  abs(z);
 ***/

Solution #2 by Charles Patridge /*****************************************************************/ /*** repeatfn.sas ***/ /*** Author: Charles Patridge ***/ /*** ***/ /*** Purpose is to apply the same function for a list of sas ***/ /*** variables where function requires only a single variable.***/ /*** It then creates the sas variables of the output of the ***/ /*** desired function and keeps them in the same dataset. ***/ /*** ***/ /*** User needs to be careful of the functions called on ***/ /*** certain variables for appropriate values. ***/ /*** ***/ /*** 1st parameter: list of sas vars for function to be ***/ /*** applied to. ***/ /*** ***/ /*** 2nd parameter: prefix for output var name ***/ /*** ***/ /*** 3rd parameter: function to be repeated ***/ /*** ***/ /*** Names of SAS Variables should be short enough to apply ***/ /*** the user supplied prefix to not exceed max length of ***/ /*** a SAS variable (32 characters) ***/ /*** ***/ /*** ***/ /*** Only makes sense if you need to do the same function for ***/ /*** many sas variables (say more than 20) ***/ /*****************************************************************/ %MACRO REPEATFN(_varlist_, _prefix_, _function_ ); %LOCAL _J_ _NUMBER_; /*** determine number of SAS variables in _varlist_ ***/ %let _NUMBER_ = %eval( 1 + (%length(%sysfunc( compbl(&_varlist_))) - %length(%sysfunc(compress(&_varlist_))))); %DO _J_=1 %TO &_NUMBER_; /*** now generate sas code for function call ***/ &_prefix_%scan(&_varlist_, &_J_) = &_function_(%scan(&_varlist_,&_J_)); %END; %MEND REPEATFN; data test; x = 1.5; y = -2.0; z = 3.5; %REPEATFN(x y z, log_, log ); /*** do log function ***/ %REPEATFN(x y z, abs_, abs ); /*** do abs function ***/ %REPEATFN(x y z, cos_, cos ); /*** do cos function ***/ run;
Solution #3 by Peter Crawford /*-----------------------------------------------------------------------* * Program : MLOOOPSX.SOURCE * *-----------------------------------------------------------------------* * Purpose : List processing: for each element of a list * * : call a macro * * : without going through the statement boundary *-----------------------------------------------------------------------* * Author : Peter Crawford - Crawford Software Consultancy Limited * * Version : 2.1 * * Created : 14.10.02 * *-----------------------------------------------------------------------* *Modification History * * Peter Crawford 14.10.02 * prefix local macro vars with macro name, to avoid contention with any * macro vars inherited by the macro called * Peter Crawford 20.02.04 * * apply %superQ() to macro vars in tests, to avoid arithmetic in * * implicit %_eval() *-----------------------------------------------------------------------*/ %macro mLoopsX( execut = /* name of macro to invoke */ , with = /* delimited list of calls */ , withdlm= %str( ) /* list delimiter */ ) /des='execute a macro for each word in a list' ; /* examples: suppose you have a macro like %macro syk( op ); %sysfunc( getoption( &op,keyword ) ) %mend syk ; then %put oldops = %mloopsx( execut= syk, with=mprint mlogic symbolgen); loads re-usable settings for these system options The macro can operate on larger scale as a statement like %mloopsx( execut=main_process, with= London New-York Tokyo ) *********/ %if &execut eq or %superQ(with) eq %then %goto mParmError ; %local mloopsx_i mloopsx_j ; %let mloopsx_i = 1 ; %let mloopsx_j = %scan( &with, &mloopsx_i, &withdlm ); %do %until( %superQ(mloopsx_j) eq ) ; %&execut.( &mloopsx_j ) %let mloopsx_i = %eval( &mloopsx_i +1 ); %let mloopsx_j = %scan( &with, &mloopsx_i, &withdlm ); %end ; %goto mExit ; %mParmError: %put mLoopsX-Error need parameters, got execut=&execut and with=&with ; %mExit: %mend mLoopsX ; /*** create your own little macro functions ***/ %macro mylog(_x_) ; log_&_x_ = log( &_x_ ); /*** log function ***/ %mend mylog; %macro myabs(_x_) ; abs_&_x_ = abs( &_x_ ); /*** abs function ***/ %mend myabs; %macro mycos(_x_) ; cos_&_x_ = cos( &_x_ ); /*** cos function ***/ %mend myabs; /*** now call your macro functions and apply them to your list of SAS variables you want ***/ %let mylist = x y z; /*** list of SAS variable I need to apply my functions to ***/ data test; x = 1; y = -2.5; z = 3.2; %mLoopsX( execut=mylog, with=&mylist ); /*** apply log ***/ %mLoopsX( execut=myabs, with=&mylist ); /*** apply abs ***/ %mLoopsX( execut=mycos, with=&mylist ); /*** apply cos ***/ run; /*** end of tip 00407 ***/