2015-10-05 50 views
0

我對SAS非常陌生,並試圖學習最佳做法。我試圖編寫一個簡單的宏來挑選特定數據集中缺少值的任何給定字段。我們的想法是遍歷每條記錄(行),並讓do(for)循環充當if語句中的OR。我的問題是SAS宏不通過整個數據集

  1. 我的理解是宏觀 - 曾稱,應該在我的數據集的每一行來執行,但在這種情況下,它似乎只進行一次執行它(也就是隻做循環似乎執行一次而不是100次)。
  2. 有沒有更好的方法來做到這一點?

    /* say I have a dataset with fieldA fieldB fieldC fieldD etc. and 100 records, some of which were missing */ 
    
    %let varList = fieldA fieldB; /* check fieldA and fieldB */ 
    %ReportIncompleteFields(sasdata.myDAta, &varList., work.tempData); 
    
    %macro ReportIncompleteFields(inDataName, chkVars, outDataName); 
    %let numVars = %sysfunc(countw(&chkVars.)); 
    
    length keepRrd 8; 
    keepRcd = 0; 
    
    data &outDataName.; 
        set &inDataName.; 
        %do ii = 1 %to &numVars.; 
         %let iiVarName = %scan(&chkVars., &ii.); 
         %if &iiVarName. = '' %then keepRcd=keepRcd+1; 
        %end; 
    
        %if keepRcd=0 %then delete; 
    run; 
    
    %mend ReportIncompleteFields; 
    

回答

2

這裏的問題不瞭解宏代碼的功能。宏代碼最常見的用途是生成SAS代碼。您的宏邏輯不會生成任何SAS代碼。

考慮您的宏代碼第一塊:

%do ii = 1 %to &numVars.; 
    %let iiVarName = %scan(&chkVars., &ii.); 
    %if &iiVarName. = '' %then keepRcd=keepRcd+1; 
%end; 

值& iiVarName將在宏變量CHKVARS列出的變量之一的名稱。這就是一串像FieldA這樣的字符。該字符串永遠不會等於彼此相鄰的兩個單引號。所以%THEN子句永遠不會生成任何代碼。即使您確實通過''作爲CHKVARS中的一個變量名稱,將生成的代碼也會丟失用於表示賦值語句結束所需的分號。數字1後面的分號將標記%IF語句的結尾。

第二個%IF語句%if keepRcd=0 %then delete;也永遠不會成立,因爲字母流keepRcd永遠不會等於數字0

所以,如果你的目標是隻保留沒有列出的字段丟失的記錄,那麼就使用CMISS()函數。例如,該程序將輸入數據集分爲GOOD和BAD數據集。

data good bad ; 
    set have ; 
    if 0=cmiss(of fieldA fieldB) then output good; 
    else output bad; 
run; 

這是如此簡單的包裝成宏可能是浪費時間。

+0

你能用數字開始一個宏變量嗎? – Reeza

+0

Reeza - 號你爲什麼問? – Tom

+0

我以爲iiVarName是在數據塊內部,SAS會將​​它解釋爲數據集中的一個變量。也就是說,我沒有檢查「iiVarName」==「,而是數據集中」iiVarName「名稱下的記錄爲空或不是。但是階梯顯然不是真的。 – adjfac

1

SAS數據步作爲一個循環,你不要在這裏需要宏觀邏輯可言,最多的數組。查看nmiss/cmiss或missing()函數。關鍵的是要確保你的變量都是相同的類型,或者聲明兩個數組和一個字符數據。這假設所有變量都具有相同的類型。如果該假設不成立,則創建兩個參數,一個用於列出字符一個變量,另一個用於數字並擴展邏輯。

%macro ReportIncompleteFields(inDataName, chkVars, outDataName); 


data &outDataName.; 
    set &inDataName.; 
    array check(*) &chkVars; 

    if nmiss(of check(*))=0;*keep all variables with no records missing; 

run; 

%mend ReportIncompleteFields; 

我不知道這是什麼了,但SAS也將自動排除casewise失蹤大多數統計特效或者它需要在默認情況下,所以你可能不需要這個數據。

+0

感謝您的反饋!我實際上想要輸出任何缺少數據的行(以確定它們是什麼)。我想我的主要問題是,在我的原代碼中,如果我用%%替換%if語句%put%else%(即,以任一方式打印),我希望能看到100次輸出,因爲我有100在我的數據行。但事實是,當我這樣做時,我只能看到%打印輸出一次 - 你知道爲什麼(或者我做錯了什麼)? – adjfac

+0

@adjfac簡而言之,SAS執行宏語句並在執行任何數據步驟代碼之前計算出您生成的數據步驟代碼*。它不會爲數據步驟的每次迭代再次運行宏語句 - 僅由宏語句生成的數據步驟代碼。 – user667489