Цикл создания новых переменных в 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_summ и sys_name_summ, которые содержат значения всех кредитов_desc в одной строке и sys_names в одной строке, разделенных запятой, пример (term_loan, business_loan) , (RM_platform, IQ_platform) Но если у клиента есть только один кредит_desc, кредит_сумм должен иметь свое значение только дважды.

Проблема при выполнении цикла do заключается в том, что после запуска этого кода я получаю набор данных только с sys_name_summ, а не с кредитом_desc_summ. Мне нужен набор данных со всеми пятью переменными facility_id, кредит_деск, sys_name, кредит_desc_summ, sys_name_summ.

Не могли бы вы помочь мне выяснить, есть ли проблема в цикле do??


person Swati Kanchan    schedule 20.08.2016    source источник


Ответы (1)


Ваш цикл всегда начинается с одного и того же набора входных данных (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 ;

Затем вы можете использовать макропеременные в операторах ARRAY, RETAIN и DROP.

person Tom    schedule 20.08.2016
comment
Привет Том, спасибо за ваш ответ. Кроме того, не могли бы вы сказать мне, всегда ли массивы более гибкие и эффективные, чем макросы? - person Swati Kanchan; 20.08.2016
comment
Макросы по определению могут быть более гибкими, поскольку они генерируют код. Но обычно лучше использовать возможности реального языка, а не использовать метаязык, такой как макрос, для генерации кода. Код будет понятнее и, возможно, быстрее. - person Tom; 20.08.2016
comment
Спасибо ! еще раз за ответ, Том. Не могли бы вы иначе сказать мне, как я могу изменить приведенный выше код на желаемый результат, который я хочу, только с помощью макроязыка. Я имею в виду, какие изменения в конечном наборе данных следует внести? - person Swati Kanchan; 20.08.2016
comment
Обновлен ответ, чтобы включить изменения, которые заставят существующую программу работать так, как вы предполагали. - person Tom; 20.08.2016
comment
что, если мы не хотим бизнес-кредит дважды, как бизнес-кредит, бизнес-кредит, а просто бизнес-кредит? @ТОМ - person Swati Kanchan; 20.08.2016
comment
Программа уже позаботится об этом. Более длинная программа делает это с помощью теста FIRST.xxx. Версия на основе массива делает это с помощью теста FINDW(). - person Tom; 21.08.2016