Working with SAS macro variables
Believe it or not, I recently had to use SAS for a simulation study because it was the only system available that could maximize the exact partial likelihood of a Cox proportional hazards model for tied data (ties=exact
) in a reasonable amount of time for a data set of 2,000 observations. This was the first time I ran a simulation in SAS. I made use of the MACRO capabilities of SAS to write generic functions that could be used to repeat steps; I might blog about my overall experience some day. Today, I'll just write about one source of frustration that I had.
In writing my simulation study, I made use of Macro Variables (%let
command) for the different scenarios I was investigating. After getting some unexpected results, I started debugging and then realized that whatever comes after the equal sign and before the semicolon of a %let
statement is what the macro variable stores. For example, if I specify %let x = 2 + log(2) / λ ;
, what gets stored in x is 2 + log(2) / λ
. When I utilize &x
, 2 + log(2) / λ
gets substituted in the code (I incorrectly assumed this expression was evaluated), which can lead to unexpected results if it were used in mathematical expressions. For instance, if in a data step I do y = z / &x
, then I might get something I wasn't expecting: z / 2 + log(2) / λ
instead of z / (2 + log(2) / λ)
. I then thought I needed to use %EVAL or %SYSEVALF, but these functions only work with additions and not other mathematical functions (e.g., log
). I also considered using CALL SYMPUTN but it could only be used in a DATA
step. My solution for getting the right math is to always surround expressions with parentheses: %let x = (log(2) / λ)
. This way, it's safe to use &x
as an entity.
To help with debugging and to see exactly how your code is running, I suggest the symbolgen
option be turned on when macros are used:
options symbolgen ; /*show macro variable resolution*/