2016-08-20 131 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再次回复。你能告诉我怎么才能通过宏语言改变上述代码所需的输出。我的意思是应该完成最终数据集中的哪些更改? –