2011-06-09 152 views
5

假設我允許用戶使用公共用戶接口寫他自己變量計算宏:如何在sas數據步驟中爲每次觀察執行一段宏?

data dataset; 
    set dataset; 
    new_var = %calculate('variable1', variable1); * This doesn't work. It just shows my indication. 
run; 

%macro calculate(var_name, var_value); 
%* Some user-defined calculation; 
%mend calculate; 

然後,在數據步驟,我可以使用用戶定義的宏計算一個新的變量

其中變量1是數據集中的變量。在這裏,我想傳入變量名稱和變量的實際值。計算之後,將值放入new_var中。

我該如何做到這一點?

+0

你會給你期待的那種用戶自定義計算的例子嗎? – 2011-06-09 13:41:44

回答

3

可以使這項工作,但你可能不正確地寫宏。您必須記住,SAS宏本質上是文本預處理器:它們輸入您編寫的代碼並輸出代碼以供給SAS [1]。

因此,這裏是一個簡單的「加法」宏:

%macro calculate (var_name, var_value); 
    &var_name + &var_value; 
%mend; 

data one; 
    input [email protected]@; 
    b = %calculate(a, 3); 
    c = %calculate(a, a); 
cards; 
1 3 -2 4 
; 
run; 

proc print data=one; 
run; 

宏設施將與由宏生成的代碼替換%calculate位,SAS實際上將看到以下內容:

%macro calculate (var_name, var_value); 
    &var_name + &var_value; 
%mend; 

data one; 
    input [email protected]@; 
    b = a + 3; 
    c = a + a; 
cards; 
1 3 -2 4 
; 
run; 

proc print data=one; 
run; 

你可以在options mprint聲明

自己的日誌文件上看到它不幸的是,這不會涵蓋可能的計算。您可能想要查找PROC FCMP以生成可在DATA步驟中使用的自定義函數/子例程的方法。

[1]我知道它比這更復雜,但你可以像這樣思考。

+0

這有點類似於我重新編碼一個特定的變量。各種數據集都需要澳大利亞各州的記錄。代碼運行了很多行。由於代碼非常直接,需要在很多程序中使用,因此我更願意將其存儲在一個宏中,並在每個程序中進行簡單調用 - 從而節省七行代碼。 – Murray 2011-06-10 06:56:20

+0

+1回答這個問題和提及PROC FCMP - FCMP絕對是要走的路。例如,請參閱下面的cmjohns回答。 – 2011-06-15 15:07:01

6

是否需要用宏實現這個功能?這聽起來像是PROC FCMP最有用的一種情況,因爲它允許您定義自己的函數或子例程(fcmp =「函數編譯器」),它可以在數據步驟中使用,就像內置函數一樣。

下面是一個簡單的例子:

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; 
+0

好點。對於這個問題,Aniko的答案更接近我所尋找的並且更簡單。但我一定會考慮proc fcmp。感謝分享知識。 – Steve 2011-06-20 22:50:27

0

這是一個常見的混淆點。問題在於SAS在任何常規代碼之前處理程序中的所有宏代碼。所以當它調用%calculate('variable1', variable1);時,它還不能訪問數據集中的數據。

也就是說,如果我有一個%*Some user-defined calculation;可能意味着什麼的例子,那麼幫助您提出解決方案會更容易。

2

我知道這是一個較舊的帖子,但我認爲這值得一提。

下面是一個解決方案,它允許使用一個宏例程,就像我們將一個函數一樣。這是在SAS resolve()功能的幫助下完成的。無論遵循「%then」(在這種情況下,它是文本,但它可能是一個數字)對應於我們將放置在「真實函數」的return()部分中的內容。

%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 
; 

結果:

v1 v2 result 
1 2 v2 is greater than v1 
2 1 v1 is greater than v2