How can I perform a piece of macro for each observation in sas data step?
Suppose I allow user to write his own variable calculation macro using a common user interface:
%macro calculate(var_name, var_value);
%* So开发者_运维技巧me user-defined calculation;
%mend calculate;
Then in a data step, I can calculate a new variable using the user-defined macro:
data dataset;
set dataset;
new_var = %calculate('variable1', variable1); * This doesn't work. It just shows my indication.
run;
Where variable1 is a variable in dataset. Here, I want to pass in the variable name and the actual value of the variable. After the calculation, put the value in new_var.
How can I achieve this?
Is it required that you achieve this with macros? This sounds like a situation where PROC FCMP
would be most useful as it allows you to define your own functions or subroutines (fcmp="function compiler") that can used in a data step just like a built-in function.
Here is a simple example:
proc fcmp outlib=sasuser.funcs.math;
function calc(var);
newvar=log(var); /*user defined stuff here - can be simple or complex*/
return(newvar);
endsub;
run;
option cmplib=sasuser.funcs; /*tell SAS where to look for functions*/
data _null_;
set sashelp.class;
newvar=calc(height); /*call your new function */
put newvar=;
run;
You can make this work, but you are probably writing the macro incorrectly. You have to remember that SAS macros are essentially text preprocessors: they input the code you have written and output code to feed to SAS [1].
So here is a simple "addition" macro:
%macro calculate (var_name, var_value);
&var_name + &var_value;
%mend;
data one;
input a@@;
b = %calculate(a, 3);
c = %calculate(a, a);
cards;
1 3 -2 4
;
run;
proc print data=one;
run;
The macro facility will replace the %calculate
bits with the code generated by the macro, and SAS will actually see the following:
%macro calculate (var_name, var_value);
&var_name + &var_value;
%mend;
data one;
input a@@;
b = a + 3;
c = a + a;
cards;
1 3 -2 4
;
run;
proc print data=one;
run;
You can see it for yourself on the log file with the options mprint
statement
Unfortunately, this will not cover all potential calculations. You might want to look up PROC FCMP
for a way to generate custom functions/subroutines usable in the DATA step.
[1] I know it is more complicated than that, but you can get far thinking like this.
I know this is an older post, but I think it's worth mentionning this.
Here's a solution that allows using a macro routine as we would a function. This is accomplished with the help of the SAS resolve()
function. Whatever follows "%then" (in this case it's text but it could be a number) corresponds to what we would put in the return() part of a "real function".
%macro compare(v1, v2);
%if &v1 > &v2 %then v1 is greater than v2;
%else v2 is greater than v1;
%mend;
data check (drop = macroCall);
input v1 v2;
macroCall = cats('%compare(', v1, ',', v2, ')');
result = resolve(macrocall);
datalines;
1 2
2 1
;
Results:
v1 v2 result
1 2 v2 is greater than v1
2 1 v1 is greater than v2
This is a common point of confusion. The problem is that SAS processes all macro code in your program BEFORE any of the regular code. So when it calls %calculate('variable1', variable1);
, it doesn't yet have access to the data in the data set.
That said, it would be easier to help you come up with a solution if I had an example of what you might mean by %*Some user-defined calculation;
.
精彩评论