执行循环以在SAS中创建新变量

时间:2016-08-20 17:14:57

标签: sas do-loops

我正在尝试运行此代码

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_summ sys_name_summ ,其中包含一行中所有loan_desc的值,以及由逗号示例分隔的一行中的sys_names(term_loan ,business_loan),(RM_platform,IQ_platform)但是如果客户只有一个loan_desc,那么loan_summ只应该有两次。

运行do循环时的问题是运行此代码后,我只获取了sys_name_summ而不是loan_desc_summ的数据集。我希望数据集包含所有五个变量 facility_id,loan_desc,sys_name,loan_desc_summ,sys_name_summ。

你能不能帮我找出do循环中是否有问题?

1 个答案:

答案 0 :(得分: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语句中的宏变量。