Как L oop через переменные форматы и переименовать в SAS - PullRequest
0 голосов
/ 21 февраля 2020

У меня есть набор данных, где каждый столбец представляет отдельную комбинацию месяца, года с февраля 2018 года по декабрь 2025 года. Эти столбцы хранятся в виде символов, но я хотел бы преобразовать их в цифры c. В настоящее время столбцы имеют названия «FEB_18», «MAR_18», «NOV_19», «JUL_22» и т. Д.

Я бы хотел, чтобы al oop брал каждую переменную и преобразовывал ее в цифру c. Первоначально я использовал следующий код, но он создает новый набор данных для каждой итерации.

 %let months = JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC;

 %MACRO DOIT(Peak=); 

    %do i= 1 %to %sysfunc(countw(&Name.));
    %let Name2 = %scan(&months., &i.);
    %do j = 18 %to 25; 

proc sql;
    create table ppl as 
        select
        input(Label, Best12.) - 21916 as Contract format MMDDYY10., /* Excel to SAS Dates*/
        input(&Name2._&j., Best12.) as _&Name2._&j.
    from Transposed_&Peak.;
    %end;
    %end;
quit;


%mend DOIT; 
%DOIT(Peak = On);

Заранее спасибо!

1 Ответ

0 голосов
/ 21 февраля 2020

Процедура CONTENTS сделает метаданные (имена столбцов, типы, номер столбца и т. Д. c) набора данных доступными в качестве данных. Из этих данных вы можете построить операторы, необходимые для выполнения преобразования

Пример:

X_feb_20 = input(feb_20, ?? best12.);  * parse value in character variable into a numeric variable;
drop feb_20;  * drop character variable from output data set;
rename x_feb_20 = feb_20;  * change the name of the numeric variable back to the orginal;

Таким образом, задача состоит в том, чтобы сделать этот шаблон для всех столбцов символов в наборе данных, имя которого представляет собой <mon>_<yy>. Тест

input('01'||transtrn(name,'_','20'),anydtdte.) is not null 

идентифицирует такие имена столбцов.

Вот пример макроса, который будет выполнять работу по дому:

/* 
 * Fake some data to play with 
 */

%macro month_columns(from_month=, to_month=);

  %local index mon yy frstdate lastdate;

  %let frstdate = %sysevalf("01&from_month"D);
  %let lastdate = %sysevalf("01&to_month"D);

  %do date = %sysevalf("01&from_month"D) %to %sysevalf("01&to_month"D);
    %let date = %sysfunc(INTNX(MONTH,&date,0,E));

    %sysfunc(putn(&date,MONNAME3))_%sysfunc(putn(&date,YEAR2.))
  %end;

%mend;

data have;
  call streaminit(123);
  do stockid = 1 to 10;
    array futures $12 %month_columns(from_month=FEB2020, to_month=DEC2025);
    do over futures;
      futures = put(rand('uniform',50) + stockid * sin(_i_/40), 12.5);
    end;
    output;
  end;
run;

/* 
 * Chore macro
 */

%macro asnum_mon_yy_columns(data=, out=);

  %local index;

  proc contents noprint data=&data out=have_columns(keep=varnum name type);
  run;

  * SQLOBS will be number of rows (and thus names) that meet the date-like criteria ;

  proc sql noprint;
    select name into :name1-
    from have_columns
    where input('01'||transtrn(name,'_','20'),anydtdte.) is not null 
      and type = 2
    order by varnum
    ;
  quit;

  data &out;
    set &data;

    %do index = 1 %to &sqlobs;
      X_&&name&index = input(&&name&index,??best12.);
    %end;

    %if &sqlobs %then %do;
      drop   %do index = 1 %to &sqlobs;
                &&name&index
             %end;
      ;
      rename %do index = 1 %to &sqlobs;
                X_&&name&index = &&name&index
             %end;
      ;
    %end;
  run;

%mend;

/*
 * Invoke chore
 */

options mprint;

%asnum_mon_yy_columns(data=have, out=want)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...