2016-08-20 119 views
0

我試圖運行此代碼Do循環中SAS

data swati; 
input facility_id$ loan_desc : $50. sys_name :$50.; 
cards; 
fac_001 term_loan  RM_platform 
fac_001 business_loan IQ_platform 
fac_002 business_loan BUSES_termloan 
fac_002 business_loan RM_platform 
fac_003 overdrafts RM_platform 
fac_003 RCF   IQ_platform 
fac_003 term_loan  BUSES_termloan 
; 

proc contents data=swati out=contents(keep=name varnum); 
run; 

proc sort data=contents; 
by varnum; 
run; 

data contents; 
set contents ; 
where varnum in (2,3); 
run; 

data contents; 
set contents; 
summary=catx('_',name, 'summ'); 
run; 

data _null_; 
set contents; 
call symput ("name" || put(_n_ , 10. -L), name); 
call symput ("summ" || put (_n_ , 10. -L), summary); 
run; 

options mlogic symbolgen mprint; 
%macro swati; 

%do i = 1 %to 2; 
proc sort data=swati; 
by facility_id &&name&i.; 
run; 

data swati1; 
set swati; 
by facility_id &&name&i.; 
length &&summ&i. $50.; 
retain &&summ&i.; 
if first.facility_id then do; 
&&summ&i.=""; 
end; 
if first.&&name&i. = last.&&name&i. then &&summ&i.=catx(',',&&name&i., &&summ&i.); 
else if first.&&name&i. ne last.&&name&i. then &&summ&i.=&&name&i.; 
run; 

if last.facility_id ; 
%end; 
%mend; 
%swati; 

此代碼將創建兩個新的變量loan_desc_summsys_name_summ其中有一條線中的所有loans_desc值創建新變量以及由逗號示例(term_loan,business_loan),(RM_platform,IQ_platform)分隔的一行中的sys_names。但是,如果客戶只有一個loan_desc,則loan_summ應該只有其值兩次。

運行do循環的問題是,在運行此代碼後,我得到的數據集只有sys_name_summ而不是loan_desc_summ。我想要包含所有五個變量的數據集facility_id,loan_desc,sys_name,loan_desc_summ,sys_name_summ。

請你幫我找出do循環中是否有問題?

回答

0

您的循環總是以相同的輸入數據集(swati)開始並生成新的數據集(SWATI1)。所以只有通過循環的最後一次纔會有效果。每個循環都需要從前一次運行的輸出開始。 您還需要修復消除重複項的邏輯。

例如,你可以在宏更改爲:

%macro swati; 
data swati1; 
    set swati; 
run; 

%do i = 1 %to 2; 
    proc sort data=swati1; 
    by facility_id &&name&i.; 
    run; 
    data swati1; 
    set swati1; 
    by facility_id &&name&i ; 
    length &&summ&i $500 ; 
    if first.facility_id then &&summ&i = ' ' ; 
    if first.&&name&i then catx(',',&&summ&i,&&name&i); 
    if last.facility_id ; 
    run; 
%end; 
%mend; 

此外,如果你只是使用數組你的程序可能是小了很多。

data want ; 
    set have ; 
    by facility_id ; 
    array one loan_desc sys_name ; 
    array two $500 loan_desc_summ sys_name_summ ; 
    retain loan_desc_summ sys_name_summ ; 
    do i=1 to dim(one); 
    if first.facility_id then two(i)=one(i) ; 
    else if not findw(two(i),one(i),',','t') then two(i)=catx(',',two(i),one(i)); 
    end; 
    if last.facility_id; 
    drop i loan_desc sys_name ; 
run; 

如果您想使其更加靈活,可以將變量名稱列表放入宏變量中。

%let varlist=loan_desc sys_name; 

然後,您可以輕鬆生成新名稱列表。

%let varlist2=%sysfunc(tranwrd(&varlist,%str(),_summ%str()))_summ ; 

然後你就可以在ARRAYRETAINDROP語句中使用宏變量。

+0

嗨湯姆,謝謝你的回答。另外,你能告訴我數組總是比宏更靈活更高效嗎? –

+0

宏定義可以更靈活,因爲它們正在生成代碼。但通常使用實際語言的功能比使用宏等元語言生成代碼更好。代碼會更清晰,可能更快。 – Tom

+0

謝謝! Tom再次回覆。你能告訴我怎麼才能通過宏語言改變上述代碼所需的輸出。我的意思是應該完成最終數據集中的哪些更改? –