Kiteulf, The macro example supplied by Astounding is a good starting point. Except for a small glitch: rather than using a KEEP statement to keep the output variables, I would use a DROP statement to drop the input variables. That way, you can get away with using multiple macro calls in the same data step. I would write the macro something like this (not tested): %macro calc (varname);
do;
PSI _&varname = ABS((DEV_&varname - &varname)*log(DEV_&varname / &varname))/100;
length ALERT_&varname $25; select; when(missing(PSI_&varname)) ALERT_&varname ='OBS - ingen observasjoner'; when(PSI_&varname <= 0.05) ALERT_&varname = 'Normal PSI'; when(PSI_&varname <= 0.1) ALERT_&varname = 'OBS - Avvik fra PSI oppdaget'; when(PSI_&varname <= 0.2) ALERT_&varname ='OBS! - Høy PSI oppdaget'; when(PSI_&varname <= 0.3) ALERT_&varname ='OBS!! - Svært høy PSI oppdaget'; otherwise ALERT_&varname ='OBS!!! - Ekstermt høy PSI oppdaget'; end;
drop DEV_&varname &varname;
end
%mend calc; I changed the IF statements to a SELECT, in order to make the code run faster. The way your code was written, a high value would first be assigned the default, then it would be rewritten each time the PSI value was shown to be higher. And a normal value would only be written once, but it would be tested in every IF statement. Instead, with the SELECT statement, the output variable only gets written once, and the PSI is tested as few times as possible. To use the SELECT statement like this, it is important to remember that the order of the statements is crucially important - the smallest value (missing) first, and then compare to increasing limits. You could also write it with descending values (using ">" instead of "<=", and the missing case in the OTHERWISE), but I assumed that the normal (small) values would be most frequent, meaning that the code would run faster that way. Instead of using KEEP (when you use KEEP several times, with different variables, what is actually going to be kept?), I used DROP to drop the input variables, which will work even if you call the macro many times in the same datastep. Note that I wrapped the code in the macro in DO; - END, and did not put a semicolon after the final END. This style of coding means that the macro can (and should) be used just like a normal SAS statement, and you can write code like data X;
set Y;
if p>4 then
%calc(a);
else
%calc(b);
run; Regards, Søren
... View more